[gnome-bluetooth] bluetooth-client: Remove all devices on adapter removal



commit c437c729b5ee52926f4a6b6006f8a085427ca7e4
Author: Benjamin Berg <bberg redhat com>
Date:   Fri Dec 15 20:42:37 2017 +0100

    bluetooth-client: Remove all devices on adapter removal
    
    If bluetoothd fails badly (e.g. kill -9), then the devices may not be
    removed before the adapter is removed. So clean up any left over device
    at adapter removal as otherwise the "device-removed" signal is not fired.
    
    Without this one ends up with stale entries in the bluetooth settings
    widget after killing bluetoothd.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=791727

 lib/bluetooth-client.c |   20 +++++++++++++++++++-
 1 files changed, 19 insertions(+), 1 deletions(-)
---
diff --git a/lib/bluetooth-client.c b/lib/bluetooth-client.c
index 109cfd4..6bf16da 100644
--- a/lib/bluetooth-client.c
+++ b/lib/bluetooth-client.c
@@ -451,6 +451,7 @@ device_removed (const char      *path,
        GtkTreeIter iter;
 
        if (get_iter_from_path(priv->store, &iter, path) == TRUE) {
+               /* Note that removal can also happen from adapter_removed. */
                g_signal_emit (G_OBJECT (client), signals[DEVICE_REMOVED], 0, path);
                gtk_tree_store_remove(priv->store, &iter);
        }
@@ -635,8 +636,9 @@ adapter_removed (GDBusObjectManager   *manager,
                 BluetoothClient      *client)
 {
        BluetoothClientPrivate *priv = BLUETOOTH_CLIENT_GET_PRIVATE(client);
-       GtkTreeIter iter;
+       GtkTreeIter iter, childiter;
        gboolean was_default;
+       gboolean have_child;
 
        if (get_iter_from_path (priv->store, &iter, path) == FALSE)
                return;
@@ -647,6 +649,22 @@ adapter_removed (GDBusObjectManager   *manager,
        if (!was_default)
                return;
 
+       /* Ensure that all devices are removed. This can happen if bluetoothd
+        * crashes as the "object-removed" signal is emitted in an undefined
+        * order. */
+       have_child = gtk_tree_model_iter_children (priv->store, &childiter, &iter);
+       while (have_child) {
+               GDBusProxy *object;
+
+               gtk_tree_model_get (GTK_TREE_MODEL(priv->store), &childiter,
+                                   BLUETOOTH_COLUMN_PROXY, &object, -1);
+
+               g_signal_emit (G_OBJECT (client), signals[DEVICE_REMOVED], 0, g_dbus_proxy_get_object_path 
(object));
+               g_object_unref (object);
+
+               have_child = gtk_tree_store_remove (priv->store, &childiter);
+       }
+
        g_clear_pointer (&priv->default_adapter, gtk_tree_row_reference_free);
        gtk_tree_store_remove (priv->store, &iter);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]