From 7953a296d409dc4b741a35bb0707f167eb6864ca Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Tue, 21 Aug 2012 13:38:17 -0400 Subject: [PATCH] ESource: Suppress "changed" emissions during initialization. If an ESource is being instantiated from a worker thread, the change notifications can possibly be emitted from callbacks on the ESource's GMainContext before the ESource is fully initialized, which can break invariants like "all ESources have a non-NULL UID string". This commit suppresses those change notifications until the ESource instance is fully initialized. --- libedataserver/e-source.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/libedataserver/e-source.c b/libedataserver/e-source.c index 219b4cf..1ed8d25 100644 --- a/libedataserver/e-source.c +++ b/libedataserver/e-source.c @@ -132,6 +132,7 @@ struct _ESourcePrivate { GHashTable *extensions; gboolean enabled; + gboolean initialized; }; struct _AsyncContext { @@ -665,6 +666,13 @@ source_idle_changed_cb (gpointer user_data) { ESource *source = E_SOURCE (user_data); + /* If the ESource is still initializing itself in a different + * thread, skip the signal emission and try again on the next + * main loop iteration. This is a busy wait but it should be + * a very short wait. */ + if (!source->priv->initialized) + return TRUE; + g_mutex_lock (source->priv->changed_lock); if (source->priv->changed != NULL) { g_source_unref (source->priv->changed); @@ -1303,15 +1311,6 @@ source_initable_init (GInitable *initable, success = source_parse_dbus_data (source, error); - /* Avoid a spurious "changed" emission. */ - g_mutex_lock (source->priv->changed_lock); - if (source->priv->changed != NULL) { - g_source_destroy (source->priv->changed); - g_source_unref (source->priv->changed); - source->priv->changed = NULL; - } - g_mutex_unlock (source->priv->changed_lock); - g_object_unref (dbus_source); /* No D-Bus object implies we're configuring a new source, @@ -1320,6 +1319,17 @@ source_initable_init (GInitable *initable, source->priv->uid = e_uid_new (); } + /* Try to avoid a spurious "changed" emission. */ + g_mutex_lock (source->priv->changed_lock); + if (source->priv->changed != NULL) { + g_source_destroy (source->priv->changed); + g_source_unref (source->priv->changed); + source->priv->changed = NULL; + } + g_mutex_unlock (source->priv->changed_lock); + + source->priv->initialized = TRUE; + return success; } -- 2.7.4