diff options
author | Ryan Lortie <desrt@desrt.ca> | 2012-08-08 16:44:06 -0400 |
---|---|---|
committer | Ryan Lortie <desrt@desrt.ca> | 2012-08-08 16:44:06 -0400 |
commit | 4a69ad00119860acce3274bdd762ae9a4c627e24 (patch) | |
tree | ad5ea5b30ef892cd450b00e8be5d0828330ab906 /dbus-1/dconf-dbus-1.c | |
parent | ea8a5f36341a9145d1b9624fcef1dae24fb69182 (diff) | |
download | dconf-4a69ad00119860acce3274bdd762ae9a4c627e24.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.
Diffstat (limited to 'dbus-1/dconf-dbus-1.c')
-rw-r--r-- | dbus-1/dconf-dbus-1.c | 19 |
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); } |