From 225071db696381c525188d4e1a29f499a160c3a8 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Thu, 2 Feb 2012 14:04:34 +0000 Subject: [PATCH 7/7] Channel contacts machinery: ref the queue item in the result Otherwise, if a caller kept a ref to the GAsyncResult after control had returned to the channel, the channel could have freed the item and its contents already. --- telepathy-glib/channel-contacts.c | 22 ++++++++++++++++++---- 1 files changed, 18 insertions(+), 4 deletions(-) diff --git a/telepathy-glib/channel-contacts.c b/telepathy-glib/channel-contacts.c index efefe38..fcb9dd0 100644 --- a/telepathy-glib/channel-contacts.c +++ b/telepathy-glib/channel-contacts.c @@ -238,6 +238,7 @@ struct _ContactsQueueItem GPtrArray *contacts; GPtrArray *ids; GArray *handles; + gsize refcount; }; static ContactsQueueItem * @@ -248,6 +249,7 @@ contacts_queue_item_new (GPtrArray *contacts, ContactsQueueItem *item; item = g_slice_new (ContactsQueueItem); + item->refcount = 1; item->contacts = contacts != NULL ? g_ptr_array_ref (contacts) : NULL; item->ids = ids != NULL ? g_ptr_array_ref (ids) : NULL; item->handles = handles != NULL ? g_array_ref (handles) : NULL; @@ -256,9 +258,19 @@ contacts_queue_item_new (GPtrArray *contacts, return item; } +static ContactsQueueItem * +contacts_queue_item_ref (ContactsQueueItem *item) +{ + item->refcount++; + return item; +} + static void -contacts_queue_item_free (ContactsQueueItem *item) +contacts_queue_item_unref (ContactsQueueItem *item) { + if (--item->refcount > 0) + return; + tp_clear_pointer (&item->contacts, g_ptr_array_unref); tp_clear_pointer (&item->ids, g_ptr_array_unref); tp_clear_pointer (&item->handles, g_array_unref); @@ -285,7 +297,7 @@ contacts_queue_head_ready (TpChannel *self, self->priv->current_item = NULL; process_contacts_queue (self); - contacts_queue_item_free (item); + contacts_queue_item_unref (item); } static void @@ -378,7 +390,7 @@ process_contacts_queue (TpChannel *self) { g_simple_async_result_set_from_error (item->result, error); g_simple_async_result_complete (item->result); - contacts_queue_item_free (item); + contacts_queue_item_unref (item); } g_object_unref (self); @@ -450,7 +462,9 @@ contacts_queue_item (TpChannel *self, item->result = g_simple_async_result_new ((GObject *) self, callback, user_data, contacts_queue_item); - g_simple_async_result_set_op_res_gpointer (item->result, item, NULL); + g_simple_async_result_set_op_res_gpointer (item->result, + contacts_queue_item_ref (item), + (GDestroyNotify) contacts_queue_item_unref); g_queue_push_tail (self->priv->contacts_queue, item); process_contacts_queue (self); -- 1.7.9