diff options
author | Lennart Poettering <lennart@poettering.net> | 2011-09-03 03:26:58 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2011-09-03 03:26:58 +0200 |
commit | ad740100d108282d0244d5739d4dcc86fe4c5fde (patch) | |
tree | 0f2be481f6ac03fb5426e450978c558c3be89ffa /src | |
parent | 43de46ab92e3b343c2e35b42cf0728a9adf48f1c (diff) |
dbus: terminate mechanism daemons after a while
Diffstat (limited to 'src')
-rw-r--r-- | src/dbus-common.c | 74 | ||||
-rw-r--r-- | src/dbus-common.h | 4 | ||||
-rw-r--r-- | src/hostnamed.c | 22 | ||||
-rw-r--r-- | src/localed.c | 22 | ||||
-rw-r--r-- | src/timedated.c | 22 |
5 files changed, 135 insertions, 9 deletions
diff --git a/src/dbus-common.c b/src/dbus-common.c index 43729f0372..40754e1e0d 100644 --- a/src/dbus-common.c +++ b/src/dbus-common.c @@ -971,3 +971,77 @@ int generic_print_property(const char *name, DBusMessageIter *iter, bool all) { return 0; } + +static void release_name_pending_cb(DBusPendingCall *pending, void *userdata) { + DBusMessage *reply; + DBusConnection *bus = userdata; + + assert_se(reply = dbus_pending_call_steal_reply(pending)); + dbus_message_unref(reply); + + dbus_connection_close(bus); +} + +void bus_async_unregister_and_exit(DBusConnection *bus, const char *name) { + DBusMessage *m = NULL; + DBusPendingCall *pending = NULL; + + assert(bus); + + /* We unregister the name here, but we continue to process + * requests, until we get the response for it, so that all + * requests are guaranteed to be processed. */ + + m = dbus_message_new_method_call( + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "ReleaseName"); + if (!m) + goto oom; + + if (!dbus_message_append_args( + m, + DBUS_TYPE_STRING, + &name, + DBUS_TYPE_INVALID)) + goto oom; + + if (!dbus_connection_send_with_reply(bus, m, &pending, -1)) + goto oom; + + if (!dbus_pending_call_set_notify(pending, release_name_pending_cb, bus, NULL)) + goto oom; + + dbus_message_unref(m); + dbus_pending_call_unref(pending); + + return; + +oom: + log_error("Out of memory"); + + if (pending) { + dbus_pending_call_cancel(pending); + dbus_pending_call_unref(pending); + } + + if (m) + dbus_message_unref(m); +} + +DBusHandlerResult bus_exit_idle_filter(DBusConnection *bus, DBusMessage *m, void *userdata) { + usec_t *remain_until = userdata; + + assert(bus); + assert(m); + assert(remain_until); + + /* Everytime we get a new message we reset out timeout */ + *remain_until = now(CLOCK_MONOTONIC) + DEFAULT_EXIT_USEC; + + if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected")) + dbus_connection_close(bus); + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} diff --git a/src/dbus-common.h b/src/dbus-common.h index aab65639c1..acd9208d66 100644 --- a/src/dbus-common.h +++ b/src/dbus-common.h @@ -167,4 +167,8 @@ int bus_iter_get_basic_and_next(DBusMessageIter *iter, int type, void *data, boo int generic_print_property(const char *name, DBusMessageIter *iter, bool all); +void bus_async_unregister_and_exit(DBusConnection *bus, const char *name); + +DBusHandlerResult bus_exit_idle_filter(DBusConnection *bus, DBusMessage *m, void *userdata); + #endif diff --git a/src/hostnamed.c b/src/hostnamed.c index e3b89a4c62..9e8825da75 100644 --- a/src/hostnamed.c +++ b/src/hostnamed.c @@ -30,6 +30,7 @@ #include "strv.h" #include "dbus-common.h" #include "polkit.h" +#include "def.h" #define INTERFACE \ " <interface name=\"org.freedesktop.hostname1\">\n" \ @@ -85,6 +86,8 @@ static char *data[_PROP_MAX] = { NULL }; +static usec_t remain_until = 0; + static void free_data(void) { int p; @@ -518,7 +521,10 @@ static int connect_bus(DBusConnection **_bus) { goto fail; } - if (!dbus_connection_register_object_path(bus, "/org/freedesktop/hostname1", &hostname_vtable, NULL)) { + dbus_connection_set_exit_on_disconnect(bus, FALSE); + + if (!dbus_connection_register_object_path(bus, "/org/freedesktop/hostname1", &hostname_vtable, NULL) || + !dbus_connection_add_filter(bus, bus_exit_idle_filter, &remain_until, NULL)) { log_error("Not enough memory"); r = -ENOMEM; goto fail; @@ -554,6 +560,7 @@ fail: int main(int argc, char *argv[]) { int r; DBusConnection *bus = NULL; + bool exiting = false; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); @@ -588,8 +595,17 @@ int main(int argc, char *argv[]) { if (r < 0) goto finish; - while (dbus_connection_read_write_dispatch(bus, -1)) - ; + remain_until = now(CLOCK_MONOTONIC) + DEFAULT_EXIT_USEC; + for (;;) { + + if (!dbus_connection_read_write_dispatch(bus, exiting ? -1 : (int) (DEFAULT_EXIT_USEC/USEC_PER_MSEC))) + break; + + if (!exiting && remain_until < now(CLOCK_MONOTONIC)) { + exiting = true; + bus_async_unregister_and_exit(bus, "org.freedesktop.hostname1"); + } + } r = 0; diff --git a/src/localed.c b/src/localed.c index d7dcc9e95b..f652110db4 100644 --- a/src/localed.c +++ b/src/localed.c @@ -29,6 +29,7 @@ #include "strv.h" #include "dbus-common.h" #include "polkit.h" +#include "def.h" #define INTERFACE \ " <interface name=\"org.freedesktop.locale1\">\n" \ @@ -108,6 +109,8 @@ static char *data[_PROP_MAX] = { NULL }; +static usec_t remain_until = 0; + static void free_data(void) { int p; @@ -537,7 +540,10 @@ static int connect_bus(DBusConnection **_bus) { goto fail; } - if (!dbus_connection_register_object_path(bus, "/org/freedesktop/locale1", &locale_vtable, NULL)) { + dbus_connection_set_exit_on_disconnect(bus, FALSE); + + if (!dbus_connection_register_object_path(bus, "/org/freedesktop/locale1", &locale_vtable, NULL) || + !dbus_connection_add_filter(bus, bus_exit_idle_filter, &remain_until, NULL)) { log_error("Not enough memory"); r = -ENOMEM; goto fail; @@ -573,6 +579,7 @@ fail: int main(int argc, char *argv[]) { int r; DBusConnection *bus = NULL; + bool exiting = false; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); @@ -604,8 +611,17 @@ int main(int argc, char *argv[]) { if (r < 0) goto finish; - while (dbus_connection_read_write_dispatch(bus, -1)) - ; + remain_until = now(CLOCK_MONOTONIC) + DEFAULT_EXIT_USEC; + for (;;) { + + if (!dbus_connection_read_write_dispatch(bus, exiting ? -1 : (int) (DEFAULT_EXIT_USEC/USEC_PER_MSEC))) + break; + + if (!exiting && remain_until < now(CLOCK_MONOTONIC)) { + exiting = true; + bus_async_unregister_and_exit(bus, "org.freedesktop.locale1"); + } + } r = 0; diff --git a/src/timedated.c b/src/timedated.c index 734538882f..b2a56e7cb0 100644 --- a/src/timedated.c +++ b/src/timedated.c @@ -29,6 +29,7 @@ #include "strv.h" #include "dbus-common.h" #include "polkit.h" +#include "def.h" #define NULL_ADJTIME_UTC "0.0 0 0\n0\nUTC\n" #define NULL_ADJTIME_LOCAL "0.0 0 0\n0\nLOCAL\n" @@ -77,6 +78,8 @@ static char *zone = NULL; static bool local_rtc = false; static int use_ntp = -1; +static usec_t remain_until = 0; + static void free_data(void) { free(zone); zone = NULL; @@ -788,7 +791,10 @@ static int connect_bus(DBusConnection **_bus) { goto fail; } - if (!dbus_connection_register_object_path(bus, "/org/freedesktop/timedate1", &timedate_vtable, NULL)) { + dbus_connection_set_exit_on_disconnect(bus, FALSE); + + if (!dbus_connection_register_object_path(bus, "/org/freedesktop/timedate1", &timedate_vtable, NULL) || + !dbus_connection_add_filter(bus, bus_exit_idle_filter, &remain_until, NULL)) { log_error("Not enough memory"); r = -ENOMEM; goto fail; @@ -824,6 +830,7 @@ fail: int main(int argc, char *argv[]) { int r; DBusConnection *bus = NULL; + bool exiting = false; log_set_target(LOG_TARGET_AUTO); log_parse_environment(); @@ -861,8 +868,17 @@ int main(int argc, char *argv[]) { goto finish; } - while (dbus_connection_read_write_dispatch(bus, -1)) - ; + remain_until = now(CLOCK_MONOTONIC) + DEFAULT_EXIT_USEC; + for (;;) { + + if (!dbus_connection_read_write_dispatch(bus, exiting ? -1 : (int) (DEFAULT_EXIT_USEC/USEC_PER_MSEC))) + break; + + if (!exiting && remain_until < now(CLOCK_MONOTONIC)) { + exiting = true; + bus_async_unregister_and_exit(bus, "org.freedesktop.hostname1"); + } + } r = 0; |