Commit 9351f54d authored by Peter Hutterer's avatar Peter Hutterer

Fix race condition causing duplicate devices in udev seats

There is a race between adding the udev monitor and enumerating current
devices. Any device added in that window will show up in both lists, causing
it to be added twice.

Fix this by comparing the syspath of any added device to the existin ones in
the seat - where it matches we can ignore the device.

Fixes #459Signed-off-by: Peter Hutterer's avatarPeter Hutterer <peter.hutterer@who-t.net>
parent 281ecf10
......@@ -41,6 +41,38 @@ udev_seat_create(struct udev_input *input,
static struct udev_seat *
udev_seat_get_named(struct udev_input *input, const char *seat_name);
static inline bool
filter_duplicates(struct udev_seat *udev_seat,
struct udev_device *udev_device)
{
struct libinput_device *device;
const char *new_syspath = udev_device_get_syspath(udev_device);
bool ignore_device = false;
if (!udev_seat)
return false;
list_for_each(device, &udev_seat->base.devices_list, link) {
const char *syspath;
struct udev_device *ud;
ud = libinput_device_get_udev_device(device);
if (!ud)
continue;
syspath = udev_device_get_syspath(ud);
if (syspath && new_syspath && streq(syspath, new_syspath))
ignore_device = true;
udev_device_unref(ud);
if (ignore_device)
break;
}
return ignore_device;
}
static int
device_added(struct udev_device *udev_device,
struct udev_input *input,
......@@ -72,6 +104,13 @@ device_added(struct udev_device *udev_device,
seat = udev_seat_get_named(input, seat_name);
/* There is a race at startup: a device added between setting
* up the udev monitor and enumerating all current devices may show
* up in both lists. Filter those out.
*/
if (filter_duplicates(seat, udev_device))
return 0;
if (seat)
libinput_seat_ref(&seat->base);
else {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment