From 2ad1dff5392e1626d714f49346ee20fb74e742ae Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 24 Apr 2006 01:48:56 +0000 Subject: [PATCH] reconnect if the DBUS daemon kicks avahi-daemon. Since the DBUS system bus socket resides outside the chroot() environment this will definitely fail if you enable chroot(). In short: this is probably not what most people want to use. (closes #25) git-svn-id: file:///home/lennart/svn/public/avahi/trunk@1197 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe --- avahi-daemon/dbus-internal.h | 4 + avahi-daemon/dbus-protocol.c | 139 +++++++++++++++++++++++++++-------- avahi-daemon/dbus-protocol.h | 2 +- avahi-daemon/main.c | 7 +- 4 files changed, 115 insertions(+), 37 deletions(-) diff --git a/avahi-daemon/dbus-internal.h b/avahi-daemon/dbus-internal.h index f91407e..11c1094 100644 --- a/avahi-daemon/dbus-internal.h +++ b/avahi-daemon/dbus-internal.h @@ -168,10 +168,14 @@ struct Client { }; struct Server { + const AvahiPoll *poll_api; DBusConnection *bus; AVAHI_LLIST_HEAD(Client, clients); int n_clients; unsigned current_id; + + AvahiTimeout *reconnect_timeout; + int reconnect; }; extern Server *server; diff --git a/avahi-daemon/dbus-protocol.c b/avahi-daemon/dbus-protocol.c index 2e3fd2f..5b9bc50 100644 --- a/avahi-daemon/dbus-protocol.c +++ b/avahi-daemon/dbus-protocol.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -61,10 +62,15 @@ /* #define VALGRIND_WORKAROUND 1 */ +#define RECONNECT_MSEC 3000 + Server *server = NULL; static int disable_user_service_publishing = 0; +static int dbus_connect(void); +static void dbus_disconnect(void); + static void client_free(Client *c) { assert(server); @@ -156,6 +162,20 @@ static Client *client_get(const char *name, int create) { return client; } +static void reconnect_callback(AvahiTimeout *t, AVAHI_GCC_UNUSED void *userdata) { + assert(!server->bus); + + if (dbus_connect() < 0) { + struct timeval tv; + avahi_log_debug(__FILE__": Connection failed, retrying in %ims...", RECONNECT_MSEC); + avahi_elapse_time(&tv, RECONNECT_MSEC, 0); + server->poll_api->timeout_update(t, &tv); + } else { + avahi_log_debug(__FILE__": Successfully reconnected."); + server->poll_api->timeout_update(t, NULL); + } +} + static DBusHandlerResult msg_signal_filter_impl(AVAHI_GCC_UNUSED DBusConnection *c, DBusMessage *m, AVAHI_GCC_UNUSED void *userdata) { DBusError error; @@ -167,12 +187,24 @@ static DBusHandlerResult msg_signal_filter_impl(AVAHI_GCC_UNUSED DBusConnection /* dbus_message_get_member(m)); */ if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected")) { - /* No, we shouldn't quit, but until we get somewhere - * usefull such that we can restore our state, we will */ - avahi_log_warn("Disconnnected from D-BUS, terminating..."); - - raise(SIGQUIT); /* The signal handler will catch this and terminate the process cleanly*/ - + struct timeval tv; + + if (server->reconnect) { + avahi_log_warn("Disconnnected from D-BUS, trying to reconnect in %ims...", RECONNECT_MSEC); + + dbus_disconnect(); + + avahi_elapse_time(&tv, RECONNECT_MSEC, 0); + + if (server->reconnect_timeout) + server->poll_api->timeout_update(server->reconnect_timeout, &tv); + else + server->reconnect_timeout = server->poll_api->timeout_new(server->poll_api, &tv, reconnect_callback, NULL); + } else { + avahi_log_warn("Disconnnected from D-BUS, exiting."); + raise(SIGQUIT); + } + return DBUS_HANDLER_RESULT_HANDLED; } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameAcquired")) { @@ -986,7 +1018,7 @@ void dbus_protocol_server_state_changed(AvahiServerState state) { int32_t t; const char *e; - if (!server) + if (!server || !server->bus) return; m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged"); @@ -1004,7 +1036,7 @@ void dbus_protocol_server_state_changed(AvahiServerState state) { dbus_message_unref(m); } -int dbus_protocol_setup(const AvahiPoll *poll_api, int _disable_user_service_publishing) { +static int dbus_connect(void) { DBusError error; static const DBusObjectPathVTable server_vtable = { @@ -1016,26 +1048,23 @@ int dbus_protocol_setup(const AvahiPoll *poll_api, int _disable_user_service_pub NULL }; - dbus_error_init(&error); - - disable_user_service_publishing = _disable_user_service_publishing; - - server = avahi_new(Server, 1); - AVAHI_LLIST_HEAD_INIT(Clients, server->clients); - server->current_id = 0; - server->n_clients = 0; + assert(server); + assert(!server->bus); + dbus_error_init(&error); + if (!(server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) { assert(dbus_error_is_set(&error)); avahi_log_error("dbus_bus_get(): %s", error.message); goto fail; } - - if (avahi_dbus_connection_glue(server->bus, poll_api) < 0) { + if (avahi_dbus_connection_glue(server->bus, server->poll_api) < 0) { avahi_log_error("avahi_dbus_connection_glue() failed"); goto fail; } + dbus_connection_set_exit_on_disconnect(server->bus, FALSE); + if (dbus_bus_request_name( server->bus, AVAHI_DBUS_NAME, @@ -1054,7 +1083,7 @@ int dbus_protocol_setup(const AvahiPoll *poll_api, int _disable_user_service_pub goto fail; } - if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) poll_api, NULL))) { + if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) server->poll_api, NULL))) { avahi_log_error("dbus_connection_add_filter() failed"); goto fail; } @@ -1072,16 +1101,68 @@ int dbus_protocol_setup(const AvahiPoll *poll_api, int _disable_user_service_pub } return 0; - fail: + + if (dbus_error_is_set(&error)) + dbus_error_free(&error); + if (server->bus) { dbus_connection_disconnect(server->bus); dbus_connection_unref(server->bus); + server->bus = NULL; } - if (dbus_error_is_set(&error)) - dbus_error_free(&error); + return -1; +} + +static void dbus_disconnect(void) { + assert(server); + + while (server->clients) + client_free(server->clients); + + assert(server->n_clients == 0); + + if (server->bus) { + dbus_connection_disconnect(server->bus); + dbus_connection_unref(server->bus); + server->bus = NULL; + } +} + +int dbus_protocol_setup(const AvahiPoll *poll_api, int _disable_user_service_publishing, int force) { + + disable_user_service_publishing = _disable_user_service_publishing; + + server = avahi_new(Server, 1); + AVAHI_LLIST_HEAD_INIT(Clients, server->clients); + server->current_id = 0; + server->n_clients = 0; + server->bus = NULL; + server->poll_api = poll_api; + server->reconnect_timeout = NULL; + server->reconnect = force; + + if (dbus_connect() < 0) { + struct timeval tv; + + if (!force) + goto fail; + + avahi_log_warn("WARNING: Failed to contact D-BUS daemon, retrying in %ims.", RECONNECT_MSEC); + + avahi_elapse_time(&tv, RECONNECT_MSEC, 0); + server->reconnect_timeout = server->poll_api->timeout_new(server->poll_api, &tv, reconnect_callback, NULL); + } + return 0; + +fail: + if (server->bus) { + dbus_connection_disconnect(server->bus); + dbus_connection_unref(server->bus); + } + avahi_free(server); server = NULL; return -1; @@ -1090,17 +1171,11 @@ fail: void dbus_protocol_shutdown(void) { if (server) { - - while (server->clients) - client_free(server->clients); - - assert(server->n_clients == 0); - - if (server->bus) { - dbus_connection_disconnect(server->bus); - dbus_connection_unref(server->bus); - } + dbus_disconnect(); + if (server->reconnect_timeout) + server->poll_api->timeout_free(server->reconnect_timeout); + avahi_free(server); server = NULL; } diff --git a/avahi-daemon/dbus-protocol.h b/avahi-daemon/dbus-protocol.h index d23b524..d4404f2 100644 --- a/avahi-daemon/dbus-protocol.h +++ b/avahi-daemon/dbus-protocol.h @@ -22,7 +22,7 @@ USA. ***/ -int dbus_protocol_setup(const AvahiPoll *poll_api, int disable_user_service_publishing); +int dbus_protocol_setup(const AvahiPoll *poll_api, int disable_user_service_publishing, int force); void dbus_protocol_shutdown(void); void dbus_protocol_server_state_changed(AvahiServerState state); diff --git a/avahi-daemon/main.c b/avahi-daemon/main.c index f32cbd6..a9dfb42 100644 --- a/avahi-daemon/main.c +++ b/avahi-daemon/main.c @@ -743,13 +743,12 @@ static int run_server(DaemonConfig *c) { #ifdef HAVE_DBUS if (c->enable_dbus) { - if (dbus_protocol_setup(poll_api, config.disable_user_service_publishing) < 0) { + if (dbus_protocol_setup(poll_api, config.disable_user_service_publishing, !c->fail_on_missing_dbus && !config.use_chroot) < 0) { + + avahi_log_warn("WARNING: Failed to contact D-BUS daemon."); if (c->fail_on_missing_dbus) goto finish; - - avahi_log_warn("WARNING: Failed to contact D-BUS daemon, disabling D-BUS support."); - c->enable_dbus = 0; } } #endif -- 2.39.5