summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRay Strode <rstrode@redhat.com>2022-10-27 09:18:53 -0400
committerRay Strode <rstrode@redhat.com>2022-10-31 15:52:52 -0400
commit709e1db83ebf8980f4367d548f12d25a69e77955 (patch)
treea318029549ac8d1e08070b515fdbefd52292219d
parent036271b5ead22c05444862781f750c6baaf0d21d (diff)
downloadgnome-online-accounts-709e1db83ebf8980f4367d548f12d25a69e77955.tar.gz
kerberos-identity: Ensure idles queued to main thread are property synchronized
Kerberos identities are refreshed on a helper thread, and the state of those identities are exported over the user bus on the main thread. Since the main consumer of an identity's properties is the bus service running on the main thread, to simplify things, property notifications are dispatched from the main thread as well (even though the underlying state is changed on a worker thread). The mechanism to dispatch property notifies to the main thread is an idle handler. The logic for doing the dispatch has a concurrency bug however. In order to coaelsce multiple notifies that happen in quick succession, the dispatch code checks for a preexisting idle id associated with the given property. That idle id is set from the worker thread when the idle is queued, and it's cleared from the main thread when the idle is dispatched. The bug is that the main thread could in theory clear the idle id immediately after the worker thread decided there was already a notify queued, leading to a notify getting completely dropped. This commit addresses the bug by adding appropriate locking. Closes https://gitlab.gnome.org/GNOME/gnome-online-accounts/-/issues/160
-rw-r--r--src/goaidentity/goakerberosidentity.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/src/goaidentity/goakerberosidentity.c b/src/goaidentity/goakerberosidentity.c
index b72ce6a..695396b 100644
--- a/src/goaidentity/goakerberosidentity.c
+++ b/src/goaidentity/goakerberosidentity.c
@@ -520,7 +520,10 @@ typedef struct
static void
clear_idle_id (NotifyRequest *request)
{
+ G_LOCK (identity_lock);
*request->idle_id = 0;
+ G_UNLOCK (identity_lock);
+
g_object_unref (request->self);
g_slice_free (NotifyRequest, request);
}