[PATCH libinput] test: make sure we search for event node, not the parent input device

Peter Hutterer peter.hutterer at who-t.net
Wed May 31 23:53:44 UTC 2017


This explains the heisenbugs when running the test suite. libevdev gives us
the syspath to the /sys/.../input123 node, not the one for the event node.
The device node path is created based on the sysfs tree, so there's a
window where the device node may not exist yet but we already returned the
device node path.

In litest, we're using a udev monitor to wait until the device is ready for
us, but the path interface only takes a device node path. So what happens is:
* libevdev gives us a syspath for the input node and a device path
* the monitor receives the input node udev device and matches the syspath
* we pass that up to the caller litest_add_device_with_overrides()
  which opens the device node and adds it to libinput
* the path interface creates a udev device from the device node, which still
  points to the old device node. Things fail because we don't have the device
  we expect or it doesn't send events and eventually times out [1].

The errors triggered by this are either odd udev property mismatches or
timeouts because events are never processed.

This race is fixed by simply constructing the actual device node path we
expect from the udev device and waiting for the right device.

[1] We rely on the caller to notify us when to remove the device and thus
silently ignore ENODEV.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 test/litest.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/test/litest.c b/test/litest.c
index a099e1fe..9fc12354 100644
--- a/test/litest.c
+++ b/test/litest.c
@@ -2721,6 +2721,7 @@ litest_create_uinput_device_from_description(const char *name,
 {
 	struct libevdev_uinput *uinput;
 	const char *syspath;
+	char path[PATH_MAX];
 
 	struct udev *udev;
 	struct udev_monitor *udev_monitor;
@@ -2744,6 +2745,7 @@ litest_create_uinput_device_from_description(const char *name,
 	uinput = litest_create_uinput(name, id, abs_info, events);
 
 	syspath = libevdev_uinput_get_syspath(uinput);
+	snprintf(path, sizeof(path), "%s/event", syspath);
 
 	/* blocking, we don't want to continue until udev is ready */
 	while (1) {
@@ -2756,7 +2758,7 @@ litest_create_uinput_device_from_description(const char *name,
 		}
 
 		udev_syspath = udev_device_get_syspath(udev_device);
-		if (udev_syspath && streq(udev_syspath, syspath))
+		if (udev_syspath && strneq(udev_syspath, path, strlen(path)))
 			break;
 
 		udev_device_unref(udev_device);
-- 
2.13.0



More information about the wayland-devel mailing list