172 lines
6.4 KiB
Diff
172 lines
6.4 KiB
Diff
From dd01fc11f599dbfe0a1d5a42e60f9364ae991d31 Mon Sep 17 00:00:00 2001
|
|
From: Ronan Pigott <ronan@rjp.ie>
|
|
Date: Fri, 18 Jul 2025 15:10:03 +0200
|
|
Subject: [PATCH] dbus: stash the subscriber list when we disconenct from the
|
|
bus
|
|
|
|
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)
|
|
|
|
Related: RHEL-75081
|
|
---
|
|
src/core/dbus.c | 23 ++++++++++++++++-------
|
|
src/core/dbus.h | 2 +-
|
|
src/core/manager.c | 5 ++++-
|
|
src/shared/bus-util.c | 22 ++++++++++++++++++++++
|
|
src/shared/bus-util.h | 1 +
|
|
5 files changed, 44 insertions(+), 9 deletions(-)
|
|
|
|
diff --git a/src/core/dbus.c b/src/core/dbus.c
|
|
index ec6c52cb85..1b8bb44eda 100644
|
|
--- a/src/core/dbus.c
|
|
+++ b/src/core/dbus.c
|
|
@@ -908,6 +908,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);
|
|
|
|
r = manager_enqueue_sync_bus_names(m);
|
|
@@ -1070,8 +1072,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, i)
|
|
if (j->bus_track && sd_bus_track_get_bus(j->bus_track) == *bus)
|
|
@@ -1131,7 +1142,6 @@ void bus_done(Manager *m) {
|
|
|
|
assert(!m->subscribed);
|
|
|
|
- m->deserialized_subscribed = strv_free(m->deserialized_subscribed);
|
|
bus_verify_polkit_async_registry_free(m->polkit_registry);
|
|
}
|
|
|
|
@@ -1229,20 +1239,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 r = 0;
|
|
+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;
|
|
}
|
|
diff --git a/src/core/dbus.h b/src/core/dbus.h
|
|
index f1c0fa86c0..402c970d74 100644
|
|
--- a/src/core/dbus.h
|
|
+++ b/src/core/dbus.h
|
|
@@ -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 manager_enqueue_sync_bus_names(Manager *m);
|
|
|
|
diff --git a/src/core/manager.c b/src/core/manager.c
|
|
index e09227d5ac..c5d906e42e 100644
|
|
--- a/src/core/manager.c
|
|
+++ b/src/core/manager.c
|
|
@@ -1348,6 +1348,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);
|
|
+
|
|
rlimit_free_all(m->rlimit);
|
|
|
|
assert(hashmap_isempty(m->units_requiring_mounts_for));
|
|
@@ -1656,7 +1659,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) {
|
|
manager_setup_bus(m);
|
|
|
|
/* Now that we are connected to all possible busses, let's deserialize who is tracking us. */
|
|
- (void) bus_track_coldplug(m, &m->subscribed, false, m->deserialized_subscribed);
|
|
+ (void) bus_track_coldplug(m->api_bus, &m->subscribed, false, m->deserialized_subscribed);
|
|
m->deserialized_subscribed = strv_free(m->deserialized_subscribed);
|
|
|
|
/* Third, fire things up! */
|
|
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
|
|
index ff0e800347..5ce4613262 100644
|
|
--- a/src/shared/bus-util.c
|
|
+++ b/src/shared/bus-util.c
|
|
@@ -1694,6 +1694,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_unrefp) sd_bus *bus = NULL;
|
|
const char *e;
|
|
diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h
|
|
index b400eb81e2..b3aa62e6e5 100644
|
|
--- a/src/shared/bus-util.h
|
|
+++ b/src/shared/bus-util.h
|
|
@@ -171,6 +171,7 @@ int bus_path_decode_unique(const char *path, const char *prefix, char **ret_send
|
|
int bus_property_get_rlimit(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
|
|
|
|
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) {
|