diff --git a/src/core/dbus.c b/src/core/dbus.c index 5e5c3ccf1b..83a4e8912e 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -812,6 +812,8 @@ static int bus_setup_api(Manager *m, sd_bus *bus) { if (r < 0) log_warning_errno(r, "Failed to register MemoryAllocation1, ignoring: %m"); + m->api_bus_ready = true; + log_debug("Successfully connected to API bus."); return 0; @@ -1104,6 +1106,8 @@ static void destroy_bus(Manager *m, sd_bus **bus) { void bus_done_api(Manager *m) { destroy_bus(m, &m->api_bus); + + m->api_bus_ready = false; } void bus_done_system(Manager *m) { diff --git a/src/core/manager.c b/src/core/manager.c index ad525539ce..e82ba36fd5 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -2892,6 +2892,14 @@ static unsigned manager_dispatch_dbus_queue(Manager *m) { assert(m); + /* If the API bus is connected but not fully set up yet (see bus_init_api()), postpone + * dispatching the queue, otherwise subscribers restored from a previous reexec would miss + * messages. The pending Varlink reload reply does not depend on the API bus, but it is held + * back too, so that the order between D-Bus messages and Varlink replies is preserved for + * clients that monitor both. */ + if (m->api_bus && !m->api_bus_ready) + return 0; + /* When we are reloading, let's not wait with generating signals, since we need to exit the manager as quickly * as we can. There's no point in throttling generation of signals in that case. */ if (MANAGER_IS_RELOADING(m) || m->send_reloading_done || m->pending_reload_message_dbus || m->pending_reload_message_vl) diff --git a/src/core/manager.h b/src/core/manager.h index 12d6cf4470..453ae74668 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -341,6 +341,11 @@ typedef struct Manager { sd_bus_track *subscribed; char **subscribed_as_strv; + /* Set once bus_setup_api() succeeded for the current API bus connection, i.e. after any + * subscriptions deserialized from a previous reload/reexec were coldplugged. Unset when the + * connection is torn down. */ + bool api_bus_ready; + /* The bus id of API bus acquired through org.freedesktop.DBus.GetId, which before deserializing * subscriptions we'd use to verify the bus is still the same instance as before. */ sd_id128_t bus_id, deserialized_bus_id;