]> 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)
committerRonan Pigott <ronan@rjp.ie>
Wed, 8 Jan 2025 22:50:56 +0000 (15:50 -0700)
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.

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

index 3f0f40e702b3c01ace35a17f30afde774c9f39a0..9abc35888d0f4cf9829d08dc32135e1b16a1d081 100644 (file)
@@ -860,6 +860,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;
@@ -1004,8 +1006,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)
@@ -1064,7 +1075,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);
 }
 
@@ -1153,20 +1163,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 f21a4f7ceb828c7b3fd24da8b17f31da829b75a0..8fb52666c0f43eced25cc662a67902859241f567 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) {
@@ -2139,7 +2142,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);
@@ -3813,9 +3816,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 8313dfdd14e8d9fbb2396e2d0e58cc8c2701846a..f6d88564b6cd36f12a5f656918fadd788fd5f958 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 e1908ecbaafff4c433428d5ffbe6779951e5f9d0..95b9adb7b1b1435f23375f4479cda532cab4d3cb 100644 (file)
@@ -66,6 +66,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) {