From 00e1b334b3014ce9ed72b5d3391313467d6fe181 Mon Sep 17 00:00:00 2001 From: Vincent Untz Date: Fri, 7 Oct 2011 15:46:51 +0200 Subject: [PATCH 1/2] lib: Disconnect signals from adapters and devices on finalize This avoids some crashes. https://bugzilla.gnome.org/show_bug.cgi?id=661118 https://bugzilla.gnome.org/show_bug.cgi?id=654172 --- lib/bluetooth-client.c | 33 +++++++++++++++++++++++++++++++++ 1 files changed, 33 insertions(+), 0 deletions(-) Index: gnome-bluetooth-3.3.2/lib/bluetooth-client.c =================================================================== --- gnome-bluetooth-3.3.2.orig/lib/bluetooth-client.c +++ gnome-bluetooth-3.3.2/lib/bluetooth-client.c @@ -80,6 +80,7 @@ struct _BluetoothClientPrivate { Manager *manager; GtkTreeStore *store; GtkTreeRowReference *default_adapter; + GSList *horrible_workaround_for_leaked_ifaces; }; enum { @@ -323,6 +324,7 @@ get_properties_for_iface (GDBusProxy *pr static GHashTable * device_list_nodes (Device *device, BluetoothClient *client) { + BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client); GHashTable *table; guint i; @@ -348,6 +350,8 @@ device_list_nodes (Device *device, Bluet g_hash_table_lookup (table, BLUEZ_AUDIOSINK_INTERFACE) == NULL) { continue; } + + priv->horrible_workaround_for_leaked_ifaces = g_slist_append (priv->horrible_workaround_for_leaked_ifaces, iface); } /* And skip interface if it's already in the hash table */ @@ -1001,6 +1005,7 @@ bluez_vanished_cb (GDBusConnection *conn static void bluetooth_client_init(BluetoothClient *client) { BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client); + GSList *l; priv->store = gtk_tree_store_new(_BLUETOOTH_NUM_COLUMNS, G_TYPE_OBJECT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, @@ -1260,6 +1265,37 @@ bluetooth_client_set_property (GObject } } +static gboolean +disconnect_from_proxy_helper (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer data) +{ + BluetoothClient *client = data; + DBusGProxy *proxy; + + gtk_tree_model_get(model, iter, + BLUETOOTH_COLUMN_PROXY, &proxy, -1); + + /* adapters */ + g_signal_handlers_disconnect_by_func(proxy, + adapter_changed, client); + g_signal_handlers_disconnect_by_func(proxy, + device_created, client); + g_signal_handlers_disconnect_by_func(proxy, + device_removed, client); + g_signal_handlers_disconnect_by_func(proxy, + device_found, client); + + /* devices */ + g_signal_handlers_disconnect_by_func(proxy, + device_changed, client); + + g_object_unref(proxy); + + return FALSE; +} + static void bluetooth_client_finalize(GObject *client) { BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client); @@ -1270,11 +1306,22 @@ static void bluetooth_client_finalize(GO g_object_unref(priv->manager); + gtk_tree_model_foreach (GTK_TREE_MODEL(priv->store), disconnect_from_proxy_helper, client); + g_object_unref(priv->store); if (priv->default_adapter) gtk_tree_row_reference_free (priv->default_adapter); + for (l = priv->horrible_workaround_for_leaked_ifaces; l != NULL; l = l->next) { + DBusGProxy *iface = l->data; + + g_signal_handlers_disconnect_by_func(iface, + device_services_changed, client); + g_object_unref (iface); + } + g_slist_free (priv->horrible_workaround_for_leaked_ifaces); + G_OBJECT_CLASS(bluetooth_client_parent_class)->finalize(client); }