summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Lortie <desrt@desrt.ca>2012-08-08 16:44:06 -0400
committerRyan Lortie <desrt@desrt.ca>2012-08-08 16:44:06 -0400
commit4a69ad00119860acce3274bdd762ae9a4c627e24 (patch)
treead5ea5b30ef892cd450b00e8be5d0828330ab906
parentea8a5f36341a9145d1b9624fcef1dae24fb69182 (diff)
downloaddconf-0.12.tar.gz
dbus-1/: fix watching for multiple sourcesdconf-0.12
When multiple sources are in use (ie: non-trivial profiles) then change monitoring needs to watch multiple D-Bus object paths. This involves sending multiple AddMatch requests and receiving multiple replies. The dbus-1 backend was only ever expecting to receive one reply, however (apparently never having been used with multiple sources). It freed its internal state object after the first reply, causing memory access errors on the subsequent replies.
-rw-r--r--dbus-1/dconf-dbus-1.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/dbus-1/dconf-dbus-1.c b/dbus-1/dconf-dbus-1.c
index 50dc0f8..64e02c4 100644
--- a/dbus-1/dconf-dbus-1.c
+++ b/dbus-1/dconf-dbus-1.c
@@ -440,6 +440,15 @@ dconf_dbus_client_scan_outstanding (DConfDBusClient *dcdbc,
*
* We just initially set it to 2, since these are the only two users.
* That way we can skip having the ref() function.
+ *
+ * We also track the number of outstanding messages that we are waiting
+ * to see before assuming that the watch has been established. This is
+ * set to the number of messages sent and decremented for each incoming
+ * reply. When it hits zero, we do one single unref.
+ *
+ * We need to keep this number separate from the refcount due to the
+ * fact that we need to do some additional checking when the last reply
+ * arrives (see code below).
*/
typedef struct
{
@@ -449,6 +458,7 @@ typedef struct
gpointer user_data;
guint64 initial_state;
gint ref_count;
+ gint n_messages;
} Watch;
@@ -555,6 +565,12 @@ add_match_done (DBusPendingCall *pending,
else
g_variant_unref (reply); /* it is just an empty tuple */
+ /* There may be multiple messages to receive replies for. Make sure
+ * we have them all before proceeding.
+ */
+ if (--watch->n_messages != 0)
+ return;
+
/* In the normal case we're done.
*
* There is a fleeting chance, however, that the database has changed
@@ -576,9 +592,10 @@ dconf_dbus_client_subscribe (DConfDBusClient *dcdbc,
{
DConfEngineMessage dcem;
Watch *watch;
-
+
watch = watch_new (dcdbc, name, notify, user_data);
dconf_engine_watch (dcdbc->engine, name, &dcem);
+ watch->n_messages = dcem.n_messages;
dconf_dbus_client_send (dcdbc, &dcem, add_match_done, watch);
dconf_engine_message_destroy (&dcem);
}