sd-bus: when the server-side disconnects, make sure to dispatch all tracking objects immediately

If the server side kicks us from the bus, from our view no names are on the bus
anymore, hence let's make sure to dispatch all tracking objects immediately.
This commit is contained in:
Lennart Poettering 2016-08-22 16:11:54 +02:00
parent 8b6e65ac32
commit 232f367766
4 changed files with 51 additions and 2 deletions

View file

@ -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))

View file

@ -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);

View file

@ -20,3 +20,4 @@
***/
void bus_track_dispatch(sd_bus_track *track);
void bus_track_close(sd_bus_track *track);

View file

@ -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,