[telepathy-mission-control/master] _mcd_dispatch_operation_set_handler_failed: fail any pending HandleWith calls if the nominated handler fails HandleChannels

Simon McVittie simon.mcvittie at collabora.co.uk
Wed Oct 28 14:15:40 PDT 2009


This is a behaviour change: HandleWith with a non-empty argument will
no longer count as general approval; so in
dispatcher/handle-channels-fails, when the first client fails, the second
won't run immediately.
---
 src/mcd-dispatch-operation.c                     |   28 +++++++++++-
 test/twisted/dispatcher/handle-channels-fails.py |   51 +++++++++++++++++++---
 2 files changed, 71 insertions(+), 8 deletions(-)

diff --git a/src/mcd-dispatch-operation.c b/src/mcd-dispatch-operation.c
index b70015d..d89941e 100644
--- a/src/mcd-dispatch-operation.c
+++ b/src/mcd-dispatch-operation.c
@@ -1521,8 +1521,11 @@ _mcd_dispatch_operation_check_finished (McdDispatchOperation *self)
 
 static void
 _mcd_dispatch_operation_set_handler_failed (McdDispatchOperation *self,
-                                            const gchar *bus_name)
+                                            const gchar *bus_name,
+                                            const GError *error)
 {
+    GList *iter, *next;
+
     if (self->priv->failed_handlers == NULL)
     {
         self->priv->failed_handlers = g_hash_table_new_full (g_str_hash,
@@ -1534,6 +1537,27 @@ _mcd_dispatch_operation_set_handler_failed (McdDispatchOperation *self,
      * will do nicely */
     g_hash_table_insert (self->priv->failed_handlers, g_strdup (bus_name),
                          self->priv->failed_handlers);
+
+    for (iter = g_queue_peek_head_link (self->priv->approvals);
+         iter != NULL;
+         iter = next)
+    {
+        Approval *approval = iter->data;
+
+        /* do this before we potentially free the list element */
+        next = iter->next;
+
+        /* If this approval wanted the same handler that just failed, then
+         * we can assume that's not going to happen. */
+        if (approval->type == APPROVAL_TYPE_HANDLE_WITH &&
+            !tp_strdiff (approval->client_bus_name, bus_name))
+        {
+            dbus_g_method_return_error (approval->context, error);
+            approval->context = NULL;
+            approval_free (approval);
+            g_queue_delete_link (self->priv->approvals, iter);
+        }
+    }
 }
 
 static gboolean
@@ -1624,7 +1648,7 @@ _mcd_dispatch_operation_handle_channels_cb (TpClient *client,
         DEBUG ("error: %s", error->message);
 
         _mcd_dispatch_operation_set_handler_failed (self,
-            tp_proxy_get_bus_name (client));
+            tp_proxy_get_bus_name (client), error);
     }
     else
     {
diff --git a/test/twisted/dispatcher/handle-channels-fails.py b/test/twisted/dispatcher/handle-channels-fails.py
index 7f532d7..5c19733 100644
--- a/test/twisted/dispatcher/handle-channels-fails.py
+++ b/test/twisted/dispatcher/handle-channels-fails.py
@@ -156,22 +156,61 @@ def test(q, bus, mc):
     # Empathy rejects the channels
     q.dbus_raise(e.message, cs.NOT_AVAILABLE, 'Blind drunk', bus=empathy_bus)
 
+    e = q.expect('dbus-error', method='HandleWith')
+    assert e.error.get_dbus_name() == cs.NOT_AVAILABLE
+    assert e.error.get_dbus_message() == 'Blind drunk'
+
+    # The channels no longer count as having been approved. Check that MC
+    # doesn't carry on regardless
+    forbidden = [EventPattern('dbus-method-call', method='HandleChannels')]
+    q.forbid_events(forbidden)
+    sync_dbus(bus, q, mc)
+    q.unforbid_events(forbidden)
+
+    if 0: # FIXME: in future this should be what happens...
+        # I'm Feeling Lucky. It might work if I try again? Maybe?
+        call_async(q, cdo_iface, 'HandleWith',
+                cs.tp_name_prefix + '.Client.Empathy')
+
+        # Empathy is asked to handle the channels, again
+        e = q.expect('dbus-method-call',
+                path=empathy.object_path,
+                interface=cs.HANDLER, method='HandleChannels',
+                handled=False)
+
+        # Empathy rejects the channels, again
+        q.dbus_raise(e.message, cs.NOT_CAPABLE, 'Still drunk', bus=empathy_bus)
+
+        e = q.expect('dbus-error', method='HandleWith')
+        assert e.error.get_dbus_name() == cs.NOT_CAPABLE
+        assert e.error.get_dbus_message() == 'Still drunk'
+
+    # OK, OK, is anyone else competent enough to handle them?
+    # (Also, assert that MC doesn't offer them back to Empathy, knowing that
+    # it already tried and failed)
+    forbidden = [EventPattern('dbus-method-call', method='HandleChannels',
+        path=empathy.object_path)]
+    q.forbid_events(forbidden)
+    call_async(q, cdo_iface, 'HandleWith', '')
+
     # Kopete is asked to handle the channels
-    (k,) = q.expect_many(
-            EventPattern(
-                'dbus-method-call',
+    k = q.expect('dbus-method-call',
                 path=kopete.object_path,
                 interface=cs.HANDLER, method='HandleChannels',
-                handled=False),
-            )
+                handled=False)
 
     # Kopete rejects the channels too
     q.dbus_raise(k.message, cs.NOT_AVAILABLE, 'Also blind drunk',
             bus=kopete_bus)
 
+    e = q.expect('dbus-error', method='HandleWith')
+
+    if 0: # FIXME: at the moment the error is a generic "no more handlers"
+        assert e.error.get_dbus_name() == cs.NOT_AVAILABLE
+        assert e.error.get_dbus_message() == 'Also blind drunk'
+
     # MC gives up and closes the channel. This is the end of the CDO.
     q.expect_many(
-            EventPattern('dbus-error', method='HandleWith'),
             EventPattern('dbus-method-call', path=chan.object_path,
                 interface=cs.CHANNEL, method='Close', args=[]),
             EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
-- 
1.5.6.5




More information about the telepathy-commits mailing list