gdbusnamewatching: Check cancellation of a watch before calling back

It’s possible for `g_bus_unwatch_name()` to be called after a
name-appeared or name-vanished handler has been scheduled to be called
in another thread, but before that callback is actually invoked. If so,
the subscribing thread will receive a callback after it’s called
`g_bus_unwatch_name()`, which is unexpected and could cause bugs.

Double-check `client->cancelled` in the target thread before actually
invoking the callback.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Fixes: #604
This commit is contained in:
Philip Withnall 2020-01-20 19:17:13 +00:00
parent 79792574d4
commit 73a33e5019

View File

@ -148,6 +148,11 @@ call_handler_data_free (CallHandlerData *data)
static void static void
actually_do_call (Client *client, GDBusConnection *connection, const gchar *name_owner, CallType call_type) actually_do_call (Client *client, GDBusConnection *connection, const gchar *name_owner, CallType call_type)
{ {
/* The client might have been cancelled (g_bus_unwatch_name()) while we were
* sitting in the #GMainContext dispatch queue. */
if (client->cancelled)
return;
switch (call_type) switch (call_type)
{ {
case CALL_TYPE_NAME_APPEARED: case CALL_TYPE_NAME_APPEARED: