[telepathy-mission-control/master] McdDispatcher: disconnect from McdClientProxy signals whenever we drop a proxy

Simon McVittie simon.mcvittie at collabora.co.uk
Wed Sep 23 09:46:30 PDT 2009


In particular, this guarantees that even if a client proxy outlives the
dispatcher, the dispatcher's callbacks won't be invoked when the client
finds out its unique name or becomes ready.

Each call to mcd_dispatcher_discard_client is annotated with an
explanation of why either it can't leak startup locks, or it doesn't matter
if it does.
---
 src/mcd-dispatcher.c |   47 ++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 42 insertions(+), 5 deletions(-)

diff --git a/src/mcd-dispatcher.c b/src/mcd-dispatcher.c
index a165cf5..df27dee 100644
--- a/src/mcd-dispatcher.c
+++ b/src/mcd-dispatcher.c
@@ -1696,11 +1696,31 @@ _mcd_dispatcher_finalize (GObject * object)
     G_OBJECT_CLASS (mcd_dispatcher_parent_class)->finalize (object);
 }
 
+static void mcd_client_start_introspection (McdClientProxy *client,
+                                            McdDispatcher *dispatcher);
+
+static void mcd_dispatcher_client_ready_cb (McdClientProxy *client,
+                                            McdDispatcher *dispatcher);
+
+static void
+mcd_dispatcher_discard_client (McdDispatcher *self,
+                               McdClientProxy *client)
+{
+    g_signal_handlers_disconnect_by_func (client,
+                                          mcd_client_start_introspection,
+                                          self);
+    g_signal_handlers_disconnect_by_func (client,
+                                          mcd_dispatcher_client_ready_cb,
+                                          self);
+}
+
 static void
 _mcd_dispatcher_dispose (GObject * object)
 {
     McdDispatcherPrivate *priv = MCD_DISPATCHER_PRIV (object);
-    
+    gpointer client_p;
+    GHashTableIter iter;
+
     if (priv->is_disposed)
     {
 	return;
@@ -1713,6 +1733,17 @@ _mcd_dispatcher_dispose (GObject * object)
         priv->handler_map = NULL;
     }
 
+    g_hash_table_iter_init (&iter, priv->clients);
+
+    while (g_hash_table_iter_next (&iter, NULL, &client_p))
+    {
+        /* The client hasn't necessarily found out its unique name yet, so
+         * the startup lock might never get unlocked. However, if we're
+         * already shutting down, we don't want to start dispatching anyway. */
+        mcd_dispatcher_discard_client ((McdDispatcher *) object, client_p);
+        g_hash_table_iter_remove (&iter);
+    }
+
     g_hash_table_destroy (priv->clients);
     g_hash_table_destroy (priv->connections);
 
@@ -2021,9 +2052,6 @@ mcd_dispatcher_client_ready_cb (McdClientProxy *client,
                                 McdDispatcher *dispatcher)
 {
     DEBUG ("%s", tp_proxy_get_bus_name (client));
-
-    /* FIXME: in theory, the McdDispatcher might not still be alive at this
-     * point? */
 }
 
 /* Check the list of strings whether they are valid well-known names of
@@ -2075,7 +2103,9 @@ mcd_dispatcher_add_client (McdDispatcher *self,
 
     DEBUG ("Register client %s", name);
 
-    /* paired with one in mcd_client_start_introspection */
+    /* paired with one in mcd_client_start_introspection - if
+     * unique-name-known is never received, then we'll never start
+     * dispatching, but that can only happen during dispose */
     if (!self->priv->startup_completed)
         self->priv->startup_lock++;
 
@@ -2223,6 +2253,13 @@ name_owner_changed_cb (TpDBusDaemon *proxy,
                  * filters */
                 _mcd_client_proxy_become_incapable (client);
                 mcd_dispatcher_update_client_caps (self, client);
+
+                /* This disconnects from unique-name-known without unlocking
+                 * the startup lock, but in practice the unique name was set
+                 * to "" by the _mcd_client_proxy_set_inactive call above, so
+                 * any startup lock held on the client's behalf has already
+                 * been released. */
+                mcd_dispatcher_discard_client (self, client);
                 g_hash_table_remove (priv->clients, name);
             }
         }
-- 
1.5.6.5




More information about the telepathy-commits mailing list