mirror of
https://github.com/systemd/systemd.git
synced 2025-02-02 13:47:27 +03:00
dbus: make daemon reexecution synchronous
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
This commit is contained in:
parent
b4bd51448f
commit
b23de6af89
9
TODO
9
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 /
|
||||
|
@ -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;
|
||||
|
||||
|
46
src/dbus.c
46
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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user