From ad740100d108282d0244d5739d4dcc86fe4c5fde Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 3 Sep 2011 03:26:58 +0200 Subject: [PATCH] dbus: terminate mechanism daemons after a while --- TODO | 11 ++----- src/dbus-common.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++ src/dbus-common.h | 4 +++ src/hostnamed.c | 22 ++++++++++++-- src/localed.c | 22 ++++++++++++-- src/timedated.c | 22 ++++++++++++-- 6 files changed, 137 insertions(+), 18 deletions(-) diff --git a/TODO b/TODO index 677e1c9f..4dda3f97 100644 --- a/TODO +++ b/TODO @@ -7,18 +7,14 @@ Bugfixes: * make anaconda write timeout=0 for encrypted devices -* fix broken Sockets=syslog-ng.socket packaging - -* logind: ensure ACLs are updated on login and logout - -* fix CUPS .path unit for globbing - * service: pid file reading after reload doesn't work, since we don't reset the pid variable * make sure timeouts are applied to Type=oneshot services. Features: +* when a bus name of a service disappears from the bus make sure to queue further activation requests + * something like ConditionExec= or ExecStartPre= without failure state * service restart retry configuration @@ -106,7 +102,6 @@ Features: * move readahead files into /var, look for them with .path units * teach dbus to activate all services it finds in /etc/systemd/services/org-*.service -* figure out what happened to bluez patch * support systemd.mask= on the kernel command line. @@ -122,8 +117,6 @@ Features: * maybe introduce ExecRestartPre= -* Patch systemd-fsck to use -C and pass console fd to it - * configurable jitter for timer events * timer events with system resume diff --git a/src/dbus-common.c b/src/dbus-common.c index 43729f03..40754e1e 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 aab65639..acd9208d 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 e3b89a4c..9e8825da 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 \ " \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 d7dcc9e9..f652110d 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 \ " \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 73453888..b2a56e7c 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; -- 2.39.5