summaryrefslogtreecommitdiff
path: root/src/libsystemd/sd-bus
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsystemd/sd-bus')
-rw-r--r--src/libsystemd/sd-bus/bus-internal.h1
-rw-r--r--src/libsystemd/sd-bus/bus-track.c44
-rw-r--r--src/libsystemd/sd-bus/bus-track.h1
-rw-r--r--src/libsystemd/sd-bus/sd-bus.c7
4 files changed, 51 insertions, 2 deletions
diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h
index 216d9f62bc..13357075bf 100644
--- a/src/libsystemd/sd-bus/bus-internal.h
+++ b/src/libsystemd/sd-bus/bus-internal.h
@@ -320,6 +320,7 @@ struct sd_bus {
sd_bus_track *track_queue;
LIST_HEAD(sd_bus_slot, slots);
+ LIST_HEAD(sd_bus_track, tracks);
};
#define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC))
diff --git a/src/libsystemd/sd-bus/bus-track.c b/src/libsystemd/sd-bus/bus-track.c
index 90e0c7ae01..00e93a215f 100644
--- a/src/libsystemd/sd-bus/bus-track.c
+++ b/src/libsystemd/sd-bus/bus-track.c
@@ -39,9 +39,12 @@ struct sd_bus_track {
Hashmap *names;
LIST_FIELDS(sd_bus_track, queue);
Iterator iterator;
- bool in_queue:1;
+ bool in_list:1; /* In bus->tracks? */
+ bool in_queue:1; /* In bus->track_queue? */
bool modified:1;
bool recursive:1;
+
+ LIST_FIELDS(sd_bus_track, tracks);
};
#define MATCH_PREFIX \
@@ -101,6 +104,10 @@ static void bus_track_add_to_queue(sd_bus_track *track) {
if (!track->handler)
return;
+ /* Already closed? */
+ if (!track->in_list)
+ return;
+
LIST_PREPEND(queue, track->bus->track_queue, track);
track->in_queue = true;
}
@@ -156,6 +163,9 @@ _public_ int sd_bus_track_new(
t->userdata = userdata;
t->bus = sd_bus_ref(bus);
+ LIST_PREPEND(tracks, bus->tracks, t);
+ t->in_list = true;
+
bus_track_add_to_queue(t);
*track = t;
@@ -190,6 +200,9 @@ _public_ sd_bus_track* sd_bus_track_unref(sd_bus_track *track) {
while ((i = hashmap_steal_first(track->names)))
track_item_free(i);
+ if (track->in_list)
+ LIST_REMOVE(tracks, track->bus->tracks, track);
+
bus_track_remove_from_queue(track);
hashmap_free(track->names);
sd_bus_unref(track->bus);
@@ -403,7 +416,6 @@ void bus_track_dispatch(sd_bus_track *track) {
int r;
assert(track);
- assert(track->in_queue);
assert(track->handler);
bus_track_remove_from_queue(track);
@@ -419,6 +431,34 @@ void bus_track_dispatch(sd_bus_track *track) {
sd_bus_track_unref(track);
}
+void bus_track_close(sd_bus_track *track) {
+ struct track_item *i;
+
+ assert(track);
+
+ /* Called whenever our bus connected is closed. If so, and our track object is non-empty, dispatch it
+ * immediately, as we are closing now, but first flush out all names. */
+
+ if (!track->in_list)
+ return; /* We already closed this one, don't close it again. */
+
+ /* Remember that this one is closed now */
+ LIST_REMOVE(tracks, track->bus->tracks, track);
+ track->in_list = false;
+
+ /* If there's no name in this one anyway, we don't have to dispatch */
+ if (hashmap_isempty(track->names))
+ return;
+
+ /* Let's flush out all names */
+ while ((i = hashmap_steal_first(track->names)))
+ track_item_free(i);
+
+ /* Invoke handler */
+ if (track->handler)
+ bus_track_dispatch(track);
+}
+
_public_ void *sd_bus_track_get_userdata(sd_bus_track *track) {
assert_return(track, NULL);
diff --git a/src/libsystemd/sd-bus/bus-track.h b/src/libsystemd/sd-bus/bus-track.h
index 7d93a727d6..26bd05f5c7 100644
--- a/src/libsystemd/sd-bus/bus-track.h
+++ b/src/libsystemd/sd-bus/bus-track.h
@@ -20,3 +20,4 @@
***/
void bus_track_dispatch(sd_bus_track *track);
+void bus_track_close(sd_bus_track *track);
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index 95c37d8b19..6ee5f82e12 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -107,6 +107,7 @@ static void bus_free(sd_bus *b) {
assert(b);
assert(!b->track_queue);
+ assert(!b->tracks);
b->state = BUS_CLOSED;
@@ -2706,6 +2707,12 @@ static int process_closing(sd_bus *bus, sd_bus_message **ret) {
if (c)
return process_closing_reply_callback(bus, c);
+ /* Then, fake-drop all remaining bus tracking references */
+ if (bus->tracks) {
+ bus_track_close(bus->tracks);
+ return 1;
+ }
+
/* Then, synthesize a Disconnected message */
r = sd_bus_message_new_signal(
bus,