mirror of
https://github.com/systemd/systemd.git
synced 2025-03-10 16:58:28 +03:00
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.
This commit is contained in:
parent
c5f95bc19b
commit
1b58645207
@ -860,6 +860,10 @@ int bus_init_api(Manager *m) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to set up API bus: %m");
|
||||
|
||||
r = bus_track_coldplug(bus, &m->subscribed, /* recursive= */ false, m->deserialized_subscribed);
|
||||
if (r < 0)
|
||||
return r;
|
||||
m->deserialized_subscribed = strv_free(m->deserialized_subscribed);
|
||||
m->api_bus = TAKE_PTR(bus);
|
||||
|
||||
return 0;
|
||||
@ -1004,8 +1008,19 @@ 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_error_errno(r, "Failed to serialize api subscribers: %m");
|
||||
r = strv_extend_strv_consume(&m->deserialized_subscribed, TAKE_PTR(subscribed), /* filter_duplicates = */ false);
|
||||
if (r < 0)
|
||||
log_error_errno(r, "Failed to record api subscribers: %m");
|
||||
|
||||
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 +1079,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 +1167,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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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--;
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user