summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dbus-manager.c4
-rw-r--r--src/dbus.c46
-rw-r--r--src/dbus.h2
-rw-r--r--src/fdset.c2
-rw-r--r--src/manager.c4
-rw-r--r--src/systemctl.c7
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;