summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2011-05-17 12:34:25 +0200
committerGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2011-05-17 12:34:25 +0200
commitc2f9bae72b15b82cdb8bad0f20bc12c09d93b6e4 (patch)
treefe8b9ef524fd9227b408155c97ed7aaac746141d
parentd04f1003cf6eae545e924b736bdaa049893633d3 (diff)
Fix race in tp_channel_dispatch_operation_claim_with_async()
Claiming the CDO will result in MC destroying it, so we have to prepare it before calling Claim(). (fdo #37280)
-rw-r--r--telepathy-glib/channel-dispatch-operation.c21
-rw-r--r--tests/dbus/base-client.c14
2 files changed, 24 insertions, 11 deletions
diff --git a/telepathy-glib/channel-dispatch-operation.c b/telepathy-glib/channel-dispatch-operation.c
index 12272288..340616ec 100644
--- a/telepathy-glib/channel-dispatch-operation.c
+++ b/telepathy-glib/channel-dispatch-operation.c
@@ -1394,7 +1394,7 @@ gboolean
}
static void
-claim_with_prepare_cb (GObject *source,
+claim_with_cb (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
@@ -1403,7 +1403,7 @@ claim_with_prepare_cb (GObject *source,
GError *error = NULL;
TpBaseClient *client;
- if (!tp_proxy_prepare_finish (self, result, &error))
+ if (!tp_channel_dispatch_operation_claim_finish (self, result, &error))
{
g_simple_async_result_take_error (main_result, error);
goto out;
@@ -1419,16 +1419,15 @@ out:
}
static void
-claim_with_cb (GObject *source,
+claim_with_prepare_cb (GObject *source,
GAsyncResult *result,
gpointer user_data)
{
TpChannelDispatchOperation *self = (TpChannelDispatchOperation *) source;
GSimpleAsyncResult *main_result = user_data;
GError *error = NULL;
- GQuark features[] = { TP_CHANNEL_DISPATCH_OPERATION_FEATURE_CORE, 0 };
- if (!tp_channel_dispatch_operation_claim_finish (self, result, &error))
+ if (!tp_proxy_prepare_finish (self, result, &error))
{
g_simple_async_result_take_error (main_result, error);
g_simple_async_result_complete (main_result);
@@ -1436,11 +1435,10 @@ claim_with_cb (GObject *source,
return;
}
- /* We have to prepare the CDO to be able to get the list of its channels */
- tp_proxy_prepare_async (self, features, claim_with_prepare_cb,
- main_result);
+ tp_channel_dispatch_operation_claim_async (self, claim_with_cb, main_result);
}
+
/**
* tp_channel_dispatch_operation_claim_with_async:
* @self: a #TpChannelDispatchOperation
@@ -1474,6 +1472,7 @@ tp_channel_dispatch_operation_claim_with_async (
gpointer user_data)
{
GSimpleAsyncResult *result;
+ GQuark features[] = { TP_CHANNEL_DISPATCH_OPERATION_FEATURE_CORE, 0 };
g_return_if_fail (TP_IS_CHANNEL_DISPATCH_OPERATION (self));
@@ -1484,8 +1483,10 @@ tp_channel_dispatch_operation_claim_with_async (
g_simple_async_result_set_op_res_gpointer (result, g_object_ref (client),
g_object_unref);
- tp_channel_dispatch_operation_claim_async (self, claim_with_cb,
- result);
+ /* We have to prepare the CDO to be able to get the list of its channels.
+ * We prepare it *before* calling Claim() as MC will destroy the CDO once it
+ * has been claimed. */
+ tp_proxy_prepare_async (self, features, claim_with_prepare_cb, result);
}
/**
diff --git a/tests/dbus/base-client.c b/tests/dbus/base-client.c
index 0fe60cd9..8263582b 100644
--- a/tests/dbus/base-client.c
+++ b/tests/dbus/base-client.c
@@ -258,7 +258,7 @@ teardown (Test *test,
g_object_unref (test->text_chan_service_2);
g_object_unref (test->text_chan_2);
- g_object_unref (test->cdo_service);
+ tp_clear_object (&test->cdo_service);
tp_cli_connection_run_disconnect (test->connection, -1, &test->error, NULL);
g_assert_no_error (test->error);
@@ -1152,6 +1152,13 @@ claim_with_cb (GObject *source,
}
static void
+cdo_finished_cb (TpTestsSimpleChannelDispatchOperation *cdo,
+ Test *test)
+{
+ tp_clear_object (&test->cdo_service);
+}
+
+static void
test_channel_dispatch_operation_claim_with_async (Test *test,
gconstpointer data G_GNUC_UNUSED)
{
@@ -1210,6 +1217,11 @@ test_channel_dispatch_operation_claim_with_async (Test *test,
handled = tp_base_client_get_handled_channels (test->base_client);
g_assert (handled == NULL);
+ /* Connect to CDO's Finished signal so we can remove it from the bus when
+ * it's claimed as MC would do. */
+ g_signal_connect (test->cdo_service, "finished",
+ G_CALLBACK (cdo_finished_cb), test);
+
/* Claim the CDO, as the client is also a Handler, it is now handling the
* channels */
tp_channel_dispatch_operation_claim_with_async (cdo, test->base_client,