summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Berg <bberg@redhat.com>2022-05-17 10:20:48 +0200
committerBenjamin Berg <bberg@redhat.com>2022-05-17 10:23:52 +0200
commit8c53faac8180911007a74b2d63e3a1de6e163bbb (patch)
tree06bf240ec680e8f97d00b15519f2004ba664d528
parentfa781e29da2016dee819095433d4f015f6fb6bff (diff)
linux: Do not rely on parent ID lookup to work at removal time
It appears that the parent ID lookup may not properly work when devices are removed. Likely, because corresponding sysfs entries may not exist anymore. Fix this by attaching the ID to the stored object, allowing us to remove it without calling device_parent_id() again. Fixes: #185
-rw-r--r--src/linux/up-enumerator-udev.c33
1 files changed, 20 insertions, 13 deletions
diff --git a/src/linux/up-enumerator-udev.c b/src/linux/up-enumerator-udev.c
index a230308..917747a 100644
--- a/src/linux/up-enumerator-udev.c
+++ b/src/linux/up-enumerator-udev.c
@@ -181,15 +181,14 @@ uevent_signal_handler_cb (UpEnumeratorUdev *self,
parent_id = device_parent_id (device);
g_debug ("device %s has parent id: %s", device_key, parent_id);
if (parent_id) {
- gboolean insert = FALSE;
- GPtrArray *devices;
+ GPtrArray *devices = NULL;
+ char *parent_id_key = NULL;
int i;
- devices = g_hash_table_lookup (self->siblings, parent_id);
- if (!devices) {
- insert = TRUE;
+ g_hash_table_lookup_extended (self->siblings, parent_id,
+ (gpointer*)&parent_id_key, (gpointer*)&devices);
+ if (!devices)
devices = g_ptr_array_new_with_free_func (g_object_unref);
- }
for (i = 0; i < devices->len; i++) {
GObject *sibling = g_ptr_array_index (devices, i);
@@ -201,8 +200,13 @@ uevent_signal_handler_cb (UpEnumeratorUdev *self,
}
g_ptr_array_add (devices, g_object_ref (obj));
- if (insert)
- g_hash_table_insert (self->siblings, g_strdup (parent_id), devices);
+ if (!parent_id_key) {
+ parent_id_key = g_strdup (parent_id);
+ g_hash_table_insert (self->siblings, parent_id_key, devices);
+ }
+
+ /* Just a reference to the hash table key */
+ g_object_set_data (obj, "udev-parent-id", parent_id_key);
}
if (up_dev)
@@ -221,14 +225,17 @@ uevent_signal_handler_cb (UpEnumeratorUdev *self,
g_autoptr(GObject) obj = NULL;
const char *key = NULL;
- g_debug ("removing device for path %s", g_udev_device_get_sysfs_path (device));
g_hash_table_steal_extended (self->known, device_key,
(gpointer*) &key, (gpointer*) &obj);
if (obj) {
- g_autofree char *parent_id = device_parent_id (device);
+ char *parent_id;
+
+ g_debug ("removing device for path %s", g_udev_device_get_sysfs_path (device));
+
+ parent_id = g_object_get_data (obj, "udev-parent-id");
- /* Remove from siblings table */
+ /* Remove from siblings table. */
if (parent_id) {
GPtrArray *devices;
@@ -244,8 +251,8 @@ uevent_signal_handler_cb (UpEnumeratorUdev *self,
if (obj && UP_IS_DEVICE (obj)) {
g_signal_emit_by_name (self, "device-removed", obj);
- } else
- g_debug ("ignoring remove event on %s", g_udev_device_get_sysfs_path (device));
+ } else if (!obj)
+ g_debug ("ignored remove event on %s", g_udev_device_get_sysfs_path (device));
}
}