chiark / gitweb /
dbus: make daemon reexecution synchronous
authorLennart Poettering <lennart@poettering.net>
Thu, 28 Apr 2011 20:07:01 +0000 (22:07 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 28 Apr 2011 20:07:01 +0000 (22:07 +0200)
We simply keep open copies of the dbus connections across the
reexecution and close them as last step of it. A client can thus simply
wait until its connection is dropped to know when the reexecution is
finished.

https://bugzilla.redhat.com/show_bug.cgi?id=698198

TODO
src/dbus-manager.c
src/dbus.c
src/dbus.h
src/fdset.c
src/manager.c
src/systemctl.c

diff --git a/TODO b/TODO
index be964623ccfb08cc599c8234d637934928bcadd4..3f26e2ea5f966cb1c121c2f4c2e1b8fc75c306a6 100644 (file)
--- a/TODO
+++ b/TODO
@@ -5,6 +5,9 @@ F15:
 * 0595f9a1c182a84581749823ef47c5f292e545f9 is borked, freezes shutdown
     (path: after installing inotify watches, recheck file again to fix race)
 
+* move systemadm man page to systemd-gtk
+  https://bugzilla.redhat.com/show_bug.cgi?id=699394
+
 F15 External:
 
 * NFS, networkmanager ordering issue (PENDING)
@@ -28,6 +31,10 @@ F15 External:
 
 Features:
 
+* drop /.readahead on bigger upgrades with yum
+
+* add inode stat() check to readahead
+
 * plymouth.enable=0
 
 * introduce dbus calls for enabling/disabling a service
@@ -60,8 +67,6 @@ Features:
 
 * rename systemd-logger to systemd-stdio-syslog-bridge
 
-* introduce /usr/lib/binfmt.d/, /usr/lib/tmpfiles.d/
-
 * take BSD file lock on tty devices when using them?
 
 * avoid any flag files, or readahead files in /, we need to support r/o /
index 9776b0b9decb73924d8693537075ad5598771996..797e53d10fc5449303de8ccc8bc92b54e7a0782a 100644 (file)
@@ -922,8 +922,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
 
         } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
 
-                if (!(reply = dbus_message_new_method_return(message)))
-                        goto oom;
+                /* We don't send a reply back here, the client should
+                 * just wait for us disconnecting. */
 
                 m->exit_code = MANAGER_REEXECUTE;
 
index 1907560bc0a144896fde86aef1f150a356cb42e7..8ea768c5a782f7f94d2bcb238767887e35315d7f 100644 (file)
@@ -598,7 +598,12 @@ static void request_name_pending_cb(DBusPendingCall *pending, void *userdata) {
 
 static int request_name(Manager *m) {
         const char *name = "org.freedesktop.systemd1";
-        uint32_t flags = 0;
+        /* Allow replacing of our name, to ease implementation of
+         * reexecution, where we keep the old connection open until
+         * after the new connection is set up and the name installed
+         * to allow clients to synchronously wait for reexecution to
+         * finish */
+        uint32_t flags = DBUS_NAME_FLAG_ALLOW_REPLACEMENT|DBUS_NAME_FLAG_REPLACE_EXISTING;
         DBusMessage *message = NULL;
         DBusPendingCall *pending = NULL;
 
@@ -1305,3 +1310,42 @@ bool bus_connection_has_subscriber(Manager *m, DBusConnection *c) {
 
         return !set_isempty(BUS_CONNECTION_SUBSCRIBED(m, c));
 }
+
+int bus_fdset_add_all(Manager *m, FDSet *fds) {
+        Iterator i;
+        DBusConnection *c;
+
+        assert(m);
+        assert(fds);
+
+        /* When we are about to reexecute we add all D-Bus fds to the
+         * set to pass over to the newly executed systemd. They won't
+         * be used there however, except that they are closed at the
+         * very end of deserialization, those making it possible for
+         * clients to synchronously wait for systemd to reexec buy
+         * simply waiting for disconnection */
+
+        SET_FOREACH(c, m->bus_connections_for_dispatch, i) {
+                int fd;
+
+                if (dbus_connection_get_unix_fd(c, &fd)) {
+                        fd = fdset_put_dup(fds, fd);
+
+                        if (fd < 0)
+                                return fd;
+                }
+        }
+
+        SET_FOREACH(c, m->bus_connections, i) {
+                int fd;
+
+                if (dbus_connection_get_unix_fd(c, &fd)) {
+                        fd = fdset_put_dup(fds, fd);
+
+                        if (fd < 0)
+                                return fd;
+                }
+        }
+
+        return 0;
+}
index 57a2b388ca5e2a7632ca2173d929c3adeb2b5d14..8387ffaa7210f60390871854a09a84e801bfa39a 100644 (file)
@@ -43,6 +43,8 @@ int bus_parse_strv(DBusMessage *m, char ***_l);
 bool bus_has_subscriber(Manager *m);
 bool bus_connection_has_subscriber(Manager *m, DBusConnection *c);
 
+int bus_fdset_add_all(Manager *m, FDSet *fds);
+
 #define BUS_CONNECTION_SUBSCRIBED(m, c) dbus_connection_get_data((c), (m)->subscribed_data_slot)
 #define BUS_PENDING_CALL_NAME(m, p) dbus_pending_call_get_data((p), (m)->name_data_slot)
 
index 29e75a03460550bf1d4e70866a451586ba86c8d7..9bf378884959997368cfa9232b2cea4a450a65f9 100644 (file)
@@ -49,7 +49,7 @@ void fdset_free(FDSet *s) {
                  * here, so that the EBADFD that valgrind will return
                  * us on close() doesn't influence us */
 
-                /* log_warning("Closing left-over fd %i", PTR_TO_FD(p)); */
+                log_debug("Closing left-over fd %i", PTR_TO_FD(p));
                 close_nointr(PTR_TO_FD(p));
         }
 
index 084b41f13e2e7e750ae8516e75b9a623f76c5287..68d43ada44f61fa6dc75091bca65703e85dba319 100644 (file)
@@ -2688,6 +2688,10 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds) {
         if (ferror(f))
                 return -EIO;
 
+        r = bus_fdset_add_all(m, fds);
+        if (r < 0)
+                return r;
+
         return 0;
 }
 
index 10c6319b4e840a21c8786eaadb74bfa5f1d89f6c..99ada38309b7e3ab02a94f99b52e270cc79b7ae4 100644 (file)
@@ -3323,6 +3323,13 @@ static int daemon_reload(DBusConnection *bus, char **args, unsigned n) {
                         goto finish;
                 }
 
+                if (streq(method, "Reexecute") && dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY)) {
+                        /* On reexecution, we expect a disconnect, not
+                         * a reply */
+                        r = 0;
+                        goto finish;
+                }
+
                 log_error("Failed to issue method call: %s", bus_error_message(&error));
                 r = -EIO;
                 goto finish;