From 7c2e6c31419fe6cc66c90361c36d9ff0b6a148f9 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 7 Aug 2012 16:22:41 +0100 Subject: [PATCH 9/9] YtsContact: don't crash if our contact or one of our services outlives us If the TpContact or one of the YtsService instances still exists after the YtsContact has been freed, and emits a signal to which the YtsContact is still subscribing, then we would crash with a use-after-free. Disconnect all of our signals to avoid that fate. --- ytstenut/yts-contact.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/ytstenut/yts-contact.c b/ytstenut/yts-contact.c index 26457dc..ac533d8 100644 --- a/ytstenut/yts-contact.c +++ b/ytstenut/yts-contact.c @@ -229,12 +229,27 @@ _set_property (GObject *object, static void _dispose (GObject *object) { + YtsContact *self = YTS_CONTACT (object); YtsContactPrivate *priv = GET_PRIVATE (object); - if (priv->services) { - g_hash_table_destroy (priv->services); - priv->services = NULL; - } + if (priv->services) + { + GHashTableIter iter; + gpointer k, v; + + g_hash_table_iter_init (&iter, priv->services); + + while (g_hash_table_iter_next (&iter, &k, &v)) + { + g_signal_handlers_disconnect_by_func (v, _service_send_message, + self); + g_signal_handlers_disconnect_by_func (v, _service_send_file, + self); + } + + g_hash_table_destroy (priv->services); + priv->services = NULL; + } if (priv->deferred_service_statuses) { g_hash_table_destroy (priv->deferred_service_statuses); @@ -242,10 +257,14 @@ _dispose (GObject *object) } // FIXME tie to tp_contact lifecycle - if (priv->tp_contact) { - g_object_unref (priv->tp_contact); - priv->tp_contact = NULL; - } + if (priv->tp_contact) + { + g_signal_handlers_disconnect_by_func (priv->tp_contact, + _tp_contact_notify_alias, self); + + g_object_unref (priv->tp_contact); + priv->tp_contact = NULL; + } G_OBJECT_CLASS (yts_contact_parent_class)->dispose (object); } -- 1.7.10.4