[dconf] GDBus thread backend: fix obscure race condition
- From: Ryan Lortie <ryanl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dconf] GDBus thread backend: fix obscure race condition
- Date: Fri, 20 Jul 2012 15:15:26 +0000 (UTC)
commit 1a580f4465d80bad209d7dccdad92063aa2861fa
Author: Ryan Lortie <desrt desrt ca>
Date: Fri Jul 20 11:07:15 2012 -0400
GDBus thread backend: fix obscure race condition
It was possible for outgoing messages to be delivered in the wrong order
due to an annoying race condition when dealing with delivery of "fast"
change messages. This was hitting the in-order assertion on return of
those messages.
The race goes like this:
- a write is requested from the main thread (1 in-flight, 0 pending)
- the reply for this first change message comes back (but is not yet
handled).
- another write is requested from the main thread and immediately
placed in-flight (with an idle on the worker thread for actually
sending it). 2 in-flight, 0 pending.
- a third write is requested from the main thread but goes to the
pending queue (since the in-flight queue is full). 2 in-flight, 1
pending.
- the reply for the first change message is now handled in the worker
thread, removing the first change from the in-flight queue. The
queue management sees the third write in the pending queue and
promotes it to the in-flight queue (properly following the second
write) but sends the message immediately since it's already in the
worker thread (leapfrogging the second write which is still waiting
in an idle).
- the idle for the second write runs
We solve this problem by dispatching all writes via idles, even if we're
already in the worker thread.
gdbus/dconf-gdbus-thread.c | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
---
diff --git a/gdbus/dconf-gdbus-thread.c b/gdbus/dconf-gdbus-thread.c
index e3d69d8..15cf70a 100644
--- a/gdbus/dconf-gdbus-thread.c
+++ b/gdbus/dconf-gdbus-thread.c
@@ -266,6 +266,7 @@ dconf_engine_dbus_call_async_func (GBusType bus_type,
GError **error)
{
DConfGDBusCall *call;
+ GSource *source;
call = g_slice_new (DConfGDBusCall);
call->bus_type = bus_type;
@@ -276,7 +277,10 @@ dconf_engine_dbus_call_async_func (GBusType bus_type,
call->parameters = g_variant_ref_sink (parameters);
call->handle = handle;
- g_main_context_invoke (dconf_gdbus_get_worker_context (), dconf_gdbus_method_call, call);
+ source = g_idle_source_new ();
+ g_source_set_callback (source, dconf_gdbus_method_call, call, NULL);
+ g_source_attach (source, dconf_gdbus_get_worker_context ());
+ g_source_unref (source);
return TRUE;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]