Only set the parent when adopting children

We use the ParentGuid quirk key to logically 'tie-together' different discrete
devices into one logical device, for instance making the USB soundcard in a hub
the child of the USB controller on the same PCB.

Setting the discrete child is sometimes correct, for instance when rebooting
the hub, the audio device also goes away -- but it's also sometimes wrong.
If we set the child for a discrete device and the parent does *not* go away
then we get to a situation where the child reference may no longer be valid
if it comes back as a different object.
When we try to remove this no-longer-valid device with the removal timeout the
daemon segfaults. This is realy bad.

Continue to allow using fu_device_add_child() in plugins, where we know the
child lifecycle is is matched by the the parent. In the engine just set the
weak parent directly and let the client use this information to show the tree
of logical devices correctly. There's no benefit to setting up the children as
referenced objects anyway.
This commit is contained in:
Richard Hughes 2020-04-09 16:03:36 +01:00
parent 6affeb84fc
commit 2ab379e6c5
2 changed files with 2 additions and 3 deletions

View File

@ -4369,7 +4369,7 @@ fu_engine_adopt_children (FuEngine *self, FuDevice *device)
fu_device_get_id (device),
fu_device_get_name (device_tmp),
fu_device_get_id (device_tmp));
fu_device_add_child (device_tmp, device);
fu_device_set_parent (device, device_tmp);
break;
}
}
@ -4389,7 +4389,7 @@ fu_engine_adopt_children (FuEngine *self, FuDevice *device)
fu_device_get_id (device_tmp),
fu_device_get_name (device),
fu_device_get_id (device));
fu_device_add_child (device, device_tmp);
fu_device_set_parent (device_tmp, device);
}
}
}

View File

@ -958,7 +958,6 @@ fu_engine_device_parent_func (gconstpointer user_data)
g_assert (fu_device_get_parent (device3) == device2);
g_assert (fu_device_get_parent (device1) == device2);
g_assert_cmpstr (fu_device_get_vendor (device3), ==, "oem");
g_assert_cmpstr (fu_device_get_vendor (device1), ==, "oem");
/* verify order */
g_assert_cmpint (fu_device_get_order (device1), ==, 0);