diff options
author | Daniel Stone <daniel@fooishbar.org> | 2006-12-06 23:21:38 +0200 |
---|---|---|
committer | Daniel Stone <daniels@endtroducing.fooishbar.org> | 2006-12-06 23:24:24 +0200 |
commit | 4cba1a1ebfbdd7ab489b1b1ffb6656cbe88eb61e (patch) | |
tree | dd095bc94fd538d3d72acae5d11ce26ba5f264d5 | |
parent | 0c5dab5c8eaa174f28054b9d20244a709c015210 (diff) |
config: bus reconnect support
Add support for reconnecting to the bus when it restarts.
-rw-r--r-- | config/config.c | 155 |
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(); } } |