diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dbus-manager.c | 4 | ||||
-rw-r--r-- | src/dbus.c | 46 | ||||
-rw-r--r-- | src/dbus.h | 2 | ||||
-rw-r--r-- | src/fdset.c | 2 | ||||
-rw-r--r-- | src/manager.c | 4 | ||||
-rw-r--r-- | src/systemctl.c | 7 |
6 files changed, 61 insertions, 4 deletions
diff --git a/src/dbus-manager.c b/src/dbus-manager.c index 9776b0b9de..797e53d10f 100644 --- a/src/dbus-manager.c +++ b/src/dbus-manager.c @@ -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; diff --git a/src/dbus.c b/src/dbus.c index 1907560bc0..8ea768c5a7 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -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; +} diff --git a/src/dbus.h b/src/dbus.h index 57a2b388ca..8387ffaa72 100644 --- a/src/dbus.h +++ b/src/dbus.h @@ -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) diff --git a/src/fdset.c b/src/fdset.c index 29e75a0346..9bf3788849 100644 --- a/src/fdset.c +++ b/src/fdset.c @@ -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)); } diff --git a/src/manager.c b/src/manager.c index 084b41f13e..68d43ada44 100644 --- a/src/manager.c +++ b/src/manager.c @@ -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; } diff --git a/src/systemctl.c b/src/systemctl.c index 10c6319b4e..99ada38309 100644 --- a/src/systemctl.c +++ b/src/systemctl.c @@ -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; |