chiark / gitweb /
dbus: terminate mechanism daemons after a while
authorLennart Poettering <lennart@poettering.net>
Sat, 3 Sep 2011 01:26:58 +0000 (03:26 +0200)
committerLennart Poettering <lennart@poettering.net>
Sat, 3 Sep 2011 01:26:58 +0000 (03:26 +0200)
TODO
src/dbus-common.c
src/dbus-common.h
src/hostnamed.c
src/localed.c
src/timedated.c

diff --git a/TODO b/TODO
index 677e1c9f4f09e18699bf5395642f64af425daf6c..4dda3f975a26c3f281d2e867a67eda22dafcc8cb 100644 (file)
--- 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
index 43729f0372a9fc70abf7cd7f1de69c0fb42ac340..40754e1e0dd195bfb0d689b2a7f705c5486a5953 100644 (file)
@@ -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;
+}
index aab65639c16cc6813894d8eb7ec951352d0a31bd..acd9208d66b85859ef08d1a9acdd59cd633d554f 100644 (file)
@@ -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
index e3b89a4c62e0b9bf7aac1de67833e8380c7668d5..9e8825da75599e3db0b27421d37910fe424c0fa1 100644 (file)
@@ -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;
 
index d7dcc9e95bbb465761ff368e5c490f2c314ec61e..f652110db49d3dec46ed5123495e7db6e8661b2d 100644 (file)
@@ -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;
 
index 734538882f8ba4bb9156f8297e11a7a1643e4de5..b2a56e7cb0d7b1f39a0f9f527443b74602f115df 100644 (file)
@@ -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;