From c2f9bae72b15b82cdb8bad0f20bc12c09d93b6e4 Mon Sep 17 00:00:00 2001 From: Guillaume Desmottes Date: Tue, 17 May 2011 12:34:25 +0200 Subject: [PATCH] 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) --- telepathy-glib/channel-dispatch-operation.c | 21 +++++++++++---------- tests/dbus/base-client.c | 14 +++++++++++++- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/telepathy-glib/channel-dispatch-operation.c b/telepathy-glib/channel-dispatch-operation.c index 1227228..340616e 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 0fe60cd..8263582 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, -- 1.7.4.1