Blob Blame History Raw
From 6b34f996699a80c249d2cccfe369b3b61e70d4ce Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer@who-t.net>
Date: Mon, 10 Dec 2018 14:43:30 +1000
Subject: [PATCH] common: fix udev-based device removal

libgudev allocs a new GUdevDevice object for each event, so the pointer value
for the 'add' udev event differs from the one for the 'remove' event. If we
use the pointer value as hash table key, we'll never remove the device.
Switch to use the syspath of the device instead, that one is unique per
device.

Fixes #309
---
 panels/common/gsd-device-manager-udev.c | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/panels/common/gsd-device-manager-udev.c b/panels/common/gsd-device-manager-udev.c
index aa9304232..105c8e987 100644
--- a/panels/common/gsd-device-manager-udev.c
+++ b/panels/common/gsd-device-manager-udev.c
@@ -122,6 +122,7 @@ add_device (GsdUdevDeviceManager *manager,
 {
 	GUdevDevice *parent;
 	GsdDevice *device;
+	gchar *syspath;
 
 	parent = g_udev_device_get_parent (udev_device);
 
@@ -129,7 +130,8 @@ add_device (GsdUdevDeviceManager *manager,
 		return;
 
 	device = create_device (udev_device);
-	g_hash_table_insert (manager->devices, g_object_ref (udev_device), device);
+	syspath = g_strdup (g_udev_device_get_sysfs_path (udev_device));
+	g_hash_table_insert (manager->devices, syspath, device);
 	g_signal_emit_by_name (manager, "device-added", device);
 }
 
@@ -138,17 +140,19 @@ remove_device (GsdUdevDeviceManager *manager,
 	       GUdevDevice	    *udev_device)
 {
 	GsdDevice *device;
+	gchar *syspath;
 
-	device = g_hash_table_lookup (manager->devices, udev_device);
+	syspath = g_strdup (g_udev_device_get_sysfs_path (udev_device));
+	device = g_hash_table_lookup (manager->devices, syspath);
 
 	if (!device)
 		return;
 
-	g_hash_table_steal (manager->devices, udev_device);
+	g_hash_table_steal (manager->devices, syspath);
 	g_signal_emit_by_name (manager, "device-removed", device);
 
 	g_object_unref (device);
-	g_object_unref (udev_device);
+	g_free (syspath);
 }
 
 static void
@@ -173,8 +177,8 @@ gsd_udev_device_manager_init (GsdUdevDeviceManager *manager)
 	const gchar *subsystems[] = { "input", NULL };
 	GList *devices, *l;
 
-	manager->devices = g_hash_table_new_full (NULL, NULL,
-						  (GDestroyNotify) g_object_unref,
+	manager->devices = g_hash_table_new_full (g_str_hash, g_str_equal,
+						  (GDestroyNotify) g_free,
 						  (GDestroyNotify) g_object_unref);
 
 	manager->udev_client = g_udev_client_new (subsystems);
-- 
2.24.0