summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stone <daniel@fooishbar.org>2006-12-06 23:21:38 +0200
committerDaniel Stone <daniels@endtroducing.fooishbar.org>2006-12-06 23:24:24 +0200
commit4cba1a1ebfbdd7ab489b1b1ffb6656cbe88eb61e (patch)
treedd095bc94fd538d3d72acae5d11ce26ba5f264d5
parent0c5dab5c8eaa174f28054b9d20244a709c015210 (diff)
config: bus reconnect support
Add support for reconnecting to the bus when it restarts.
-rw-r--r--config/config.c155
1 files changed, 118 insertions, 37 deletions
diff --git a/config/config.c b/config/config.c
index 9ecdbb43c..66a15fcba 100644
--- a/config/config.c
+++ b/config/config.c
@@ -36,10 +36,10 @@
/* the above comment lies. there is no better way. */
#include "input.h"
#include "inputstr.h"
-#include "config.h"
+#include "hotplug.h"
#include "os.h"
-#define MATCH_RULE "type='method_call',interface='org.x.config.input'"
+#define CONFIG_MATCH_RULE "type='method_call',interface='org.x.config.input'"
#define MALFORMED_MSG "[config] malformed message, dropping"
#define MALFORMED_MESSAGE() { DebugF(MALFORMED_MSG "\n"); \
@@ -50,6 +50,9 @@
ret = BadValue; \
goto unwind; }
+/* How often to attempt reconnecting when we get booted off the bus. */
+#define RECONNECT_DELAY 10000 /* in ms */
+
struct config_data {
int fd;
DBusConnection *connection;
@@ -59,6 +62,8 @@ struct config_data {
static struct config_data *configData;
+static CARD32 configReconnect(OsTimerPtr timer, CARD32 time, pointer arg);
+
static void
configWakeupHandler(pointer blockData, int err, pointer pReadMask)
{
@@ -73,6 +78,18 @@ configBlockHandler(pointer data, struct timeval **tv, pointer pReadMask)
{
}
+static void
+configTeardown(void)
+{
+ if (configData) {
+ RemoveGeneralSocket(configData->fd);
+ RemoveBlockAndWakeupHandlers(configBlockHandler, configWakeupHandler,
+ configData);
+ xfree(configData);
+ configData = NULL;
+ }
+}
+
static int
configAddDevice(DBusMessage *message, DBusMessageIter *iter, DBusError *error)
{
@@ -226,23 +243,22 @@ configMessage(DBusConnection *connection, DBusMessage *message, void *closure)
ret = configAddDevice(message, &iter, &error);
else if (strcmp(dbus_message_get_member(message), "remove") == 0)
ret = configRemoveDevice(message, &iter, &error);
- }
+ if (ret != BadDrawable && ret != BadAlloc) {
+ reply = dbus_message_new_method_return(message);
+ dbus_message_iter_init_append(reply, &iter);
- if (ret != BadDrawable && ret != BadAlloc) {
- reply = dbus_message_new_method_return(message);
- dbus_message_iter_init_append(reply, &iter);
+ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret)) {
+ ErrorF("[config] couldn't append to iterator\n");
+ dbus_error_free(&error);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &ret)) {
- ErrorF("[config] couldn't append to iterator\n");
- dbus_error_free(&error);
- return DBUS_HANDLER_RESULT_HANDLED;
- }
+ if (!dbus_connection_send(bus, reply, NULL))
+ ErrorF("[config] failed to send reply\n");
+ dbus_connection_flush(bus);
- if (!dbus_connection_send(bus, reply, NULL))
- ErrorF("[config] failed to send reply\n");
- dbus_connection_flush(bus);
-
- dbus_message_unref(reply);
+ dbus_message_unref(reply);
+ }
}
dbus_error_free(&error);
@@ -255,16 +271,40 @@ configMessage(DBusConnection *connection, DBusMessage *message, void *closure)
return DBUS_HANDLER_RESULT_HANDLED;
}
-void
-configInitialise()
+/**
+ * This is a filter, which only handles the disconnected signal, which
+ * doesn't go to the normal message handling function. This takes
+ * precedence over the message handling function, so have have to be
+ * careful to ignore anything we don't want to deal with here.
+ *
+ * Yes, this is brutally stupid.
+ */
+static DBusHandlerResult
+configFilter(DBusConnection *connection, DBusMessage *message, void *closure)
+{
+ if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL,
+ "Disconnected")) {
+ ErrorF("[dbus] disconnected from bus\n");
+ TimerSet(NULL, 0, RECONNECT_DELAY, configReconnect, NULL);
+ configTeardown();
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static Bool
+configSetup(void)
{
DBusError error;
DBusObjectPathVTable vtable = { .message_function = configMessage };
if (!configData)
configData = (struct config_data *) xcalloc(sizeof(struct config_data), 1);
- if (!configData)
- return;
+ if (!configData) {
+ ErrorF("[dbus] failed to allocate data struct.\n");
+ return FALSE;
+ }
dbus_error_init(&error);
configData->connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
@@ -272,15 +312,20 @@ configInitialise()
ErrorF("[dbus] some kind of error occurred: %s (%s)\n", error.name,
error.message);
dbus_error_free(&error);
- return;
+ xfree(configData);
+ configData = NULL;
+ return FALSE;
}
+ dbus_connection_set_exit_on_disconnect(configData->connection, FALSE);
+
if (!dbus_connection_get_unix_fd(configData->connection, &configData->fd)) {
dbus_connection_unref(configData->connection);
ErrorF("[dbus] couldn't get fd for bus\n");
dbus_error_free(&error);
- configData->fd = -1;
- return;
+ xfree(configData);
+ configData = NULL;
+ return FALSE;
}
snprintf(configData->busname, sizeof(configData->busname),
@@ -291,12 +336,13 @@ configInitialise()
error.name, error.message);
dbus_error_free(&error);
dbus_connection_unref(configData->connection);
- configData->fd = -1;
- return;
+ xfree(configData);
+ configData = NULL;
+ return FALSE;
}
/* blocks until we get a reply. */
- dbus_bus_add_match(configData->connection, MATCH_RULE, &error);
+ dbus_bus_add_match(configData->connection, CONFIG_MATCH_RULE, &error);
if (dbus_error_is_set(&error)) {
ErrorF("[dbus] couldn't match X.Org rule: %s (%s)\n", error.name,
error.message);
@@ -304,8 +350,25 @@ configInitialise()
dbus_bus_release_name(configData->connection, configData->busname,
&error);
dbus_connection_unref(configData->connection);
- configData->fd = -1;
- return;
+ xfree(configData);
+ configData = NULL;
+ return FALSE;
+ }
+
+ if (!dbus_connection_add_filter(configData->connection, configFilter,
+ configData, NULL)) {
+
+ ErrorF("[dbus] couldn't add signal filter: %s (%s)\n", error.name,
+ error.message);
+ dbus_error_free(&error);
+ dbus_bus_release_name(configData->connection, configData->busname,
+ &error);
+ dbus_bus_remove_match(configData->connection, CONFIG_MATCH_RULE,
+ &error);
+ dbus_connection_unref(configData->connection);
+ xfree(configData);
+ configData = NULL;
+ return FALSE;
}
snprintf(configData->busobject, sizeof(configData->busobject),
@@ -314,13 +377,15 @@ configInitialise()
configData->busobject, &vtable,
configData->connection)) {
ErrorF("[dbus] couldn't register object path\n");
- configData->fd = -1;
dbus_bus_release_name(configData->connection, configData->busname,
&error);
- dbus_bus_remove_match(configData->connection, MATCH_RULE, &error);
+ dbus_bus_remove_match(configData->connection, CONFIG_MATCH_RULE,
+ &error);
dbus_connection_unref(configData->connection);
dbus_error_free(&error);
- return;
+ xfree(configData);
+ configData = NULL;
+ return FALSE;
}
DebugF("[dbus] registered object path %s\n", configData->busobject);
@@ -330,6 +395,23 @@ configInitialise()
RegisterBlockAndWakeupHandlers(configBlockHandler, configWakeupHandler,
configData);
+
+ return TRUE;
+}
+
+static CARD32
+configReconnect(OsTimerPtr timer, CARD32 time, pointer arg)
+{
+ if (configSetup())
+ return 0;
+ else
+ return RECONNECT_DELAY;
+}
+
+void
+configInitialise()
+{
+ TimerSet(NULL, 0, 1, configReconnect, NULL);
}
void
@@ -341,16 +423,15 @@ configFini()
dbus_error_init(&error);
dbus_connection_unregister_object_path(configData->connection,
configData->busobject);
- dbus_bus_remove_match(configData->connection, MATCH_RULE, &error);
+ dbus_connection_remove_filter(configData->connection, configFilter,
+ configData);
+ dbus_bus_remove_match(configData->connection, CONFIG_MATCH_RULE,
+ &error);
dbus_bus_release_name(configData->connection, configData->busname,
&error);
dbus_connection_unref(configData->connection);
- RemoveGeneralSocket(configData->fd);
- RemoveBlockAndWakeupHandlers(configBlockHandler, configWakeupHandler,
- configData);
- xfree(configData);
- configData = NULL;
dbus_error_free(&error);
+ configTeardown();
}
}