]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dbus: stash the subscriber list when we disconenct from the bus
authorRonan Pigott <ronan@rjp.ie>
Thu, 28 Nov 2024 19:53:32 +0000 (12:53 -0700)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Thu, 9 Oct 2025 11:22:30 +0000 (13:22 +0200)
If we unexpectly disconnect from the bus, systemd would end up dropping
the list of subscribers, which breaks the ability of clients like logind
to monitor the state of units.

Stash the list of subscribers into the deserialized state in the event
of a disconnect so that when we recover we can renew the broken
subscriptions.

(cherry picked from commit 8402ca04d1a063c3d8a9e3d5c16df8bb8778ae98)

src/core/dbus.c
src/core/dbus.h
src/core/manager.c
src/shared/bus-util.c
src/shared/bus-util.h

index 51ad502a6b68bcab3f0450944afd3df202a460c5..dcf3de74243c0040ffe84a9159af8c20b1184a7d 100644 (file)
@@ -859,6 +859,8 @@ int bus_init_api(Manager *m) {
         if (r < 0)
                 return log_error_errno(r, "Failed to set up API bus: %m");
 
+        (void) bus_track_coldplug(bus, &m->subscribed, /* recursive= */ false, m->deserialized_subscribed);
+        m->deserialized_subscribed = strv_free(m->deserialized_subscribed);
         m->api_bus = TAKE_PTR(bus);
 
         return 0;
@@ -1002,8 +1004,17 @@ static void destroy_bus(Manager *m, sd_bus **bus) {
         }
 
         /* Get rid of tracked clients on this bus */
-        if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus)
+        if (m->subscribed && sd_bus_track_get_bus(m->subscribed) == *bus) {
+                _cleanup_strv_free_ char **subscribed = NULL;
+                int r;
+
+                r = bus_track_to_strv(m->subscribed, &subscribed);
+                if (r < 0)
+                        log_warning_errno(r, "Failed to serialize api subscribers, ignoring: %m");
+                strv_free_and_replace(m->deserialized_subscribed, subscribed);
+
                 m->subscribed = sd_bus_track_unref(m->subscribed);
+        }
 
         HASHMAP_FOREACH(j, m->jobs)
                 if (j->bus_track && sd_bus_track_get_bus(j->bus_track) == *bus)
@@ -1062,7 +1073,6 @@ void bus_done(Manager *m) {
 
         assert(!m->subscribed);
 
-        m->deserialized_subscribed = strv_free(m->deserialized_subscribed);
         m->polkit_registry = hashmap_free(m->polkit_registry);
 }
 
@@ -1151,20 +1161,19 @@ void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix) {
         }
 }
 
-int bus_track_coldplug(Manager *m, sd_bus_track **t, bool recursive, char **l) {
+int bus_track_coldplug(sd_bus *bus, sd_bus_track **t, bool recursive, char **l) {
         int r;
 
-        assert(m);
         assert(t);
 
         if (strv_isempty(l))
                 return 0;
 
-        if (!m->api_bus)
+        if (!bus)
                 return 0;
 
         if (!*t) {
-                r = sd_bus_track_new(m->api_bus, t, NULL, NULL);
+                r = sd_bus_track_new(bus, t, NULL, NULL);
                 if (r < 0)
                         return r;
         }
index d00c14d3b72ed492434613335d8e93962ac4906a..eb1baf604935695cedb47037fc7632762f2efedc 100644 (file)
@@ -19,7 +19,7 @@ void bus_done(Manager *m);
 int bus_fdset_add_all(Manager *m, FDSet *fds);
 
 void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix);
-int bus_track_coldplug(Manager *m, sd_bus_track **t, bool recursive, char **l);
+int bus_track_coldplug(sd_bus *bus, sd_bus_track **t, bool recursive, char **l);
 
 int bus_foreach_bus(Manager *m, sd_bus_track *subscribed2, int (*send_message)(sd_bus *bus, void *userdata), void *userdata);
 
index 4ccaba905412f89b42c37338bebceccd93248c08..6fef10389fbf175b0efccc4ed4e6fa078b995b1d 100644 (file)
@@ -1803,6 +1803,9 @@ Manager* manager_free(Manager *m) {
         free(m->switch_root);
         free(m->switch_root_init);
 
+        sd_bus_track_unref(m->subscribed);
+        strv_free(m->deserialized_subscribed);
+
         unit_defaults_done(&m->defaults);
 
         FOREACH_ARRAY(map, m->units_needing_mounts_for, _UNIT_MOUNT_DEPENDENCY_TYPE_MAX) {
@@ -2162,7 +2165,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds, const char *roo
                 manager_setup_bus(m);
 
                 /* Now that we are connected to all possible buses, let's deserialize who is tracking us. */
-                r = bus_track_coldplug(m, &m->subscribed, false, m->deserialized_subscribed);
+                r = bus_track_coldplug(m->api_bus, &m->subscribed, false, m->deserialized_subscribed);
                 if (r < 0)
                         log_warning_errno(r, "Failed to deserialized tracked clients, ignoring: %m");
                 m->deserialized_subscribed = strv_free(m->deserialized_subscribed);
@@ -3836,9 +3839,6 @@ int manager_reload(Manager *m) {
         /* Clean up runtime objects no longer referenced */
         manager_vacuum(m);
 
-        /* Clean up deserialized tracked clients */
-        m->deserialized_subscribed = strv_free(m->deserialized_subscribed);
-
         /* Consider the reload process complete now. */
         assert(m->n_reloading > 0);
         m->n_reloading--;
index ff80e580fc3ea4cde7f8fdd468ba0a3511ad1cdb..2cdde97b789245babdb00095a967117fcd8dda7a 100644 (file)
@@ -698,6 +698,28 @@ int bus_track_add_name_many(sd_bus_track *t, char **l) {
         return r;
 }
 
+int bus_track_to_strv(sd_bus_track *t, char ***ret) {
+        _cleanup_strv_free_ char **subscribed = NULL;
+        int r = 0;
+
+        assert(ret);
+
+        for (const char *n = sd_bus_track_first(t); n; n = sd_bus_track_next(t)) {
+                r = sd_bus_track_count_name(t, n);
+                if (r < 0)
+                        return r;
+
+                for (int j = 0; j < r; j++) {
+                        r = strv_extend(&subscribed, n);
+                        if (r < 0)
+                                return r;
+                }
+        }
+
+        *ret = TAKE_PTR(subscribed);
+        return r;
+}
+
 int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description) {
         _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
         const char *e;
index fbccb24314fe4c2a2d412f0afe62cbb93d75c7dd..83522ad1c1d30f4fcdd5db374f12b48d536b609f 100644 (file)
@@ -63,6 +63,7 @@ int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id,
 int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external);
 
 int bus_track_add_name_many(sd_bus_track *t, char **l);
+int bus_track_to_strv(sd_bus_track *t, char ***ret);
 
 int bus_open_system_watch_bind_with_description(sd_bus **ret, const char *description);
 static inline int bus_open_system_watch_bind(sd_bus **ret) {