[PATCH libinput 0/1] Initialization race against udev

Matt Hoosier matt.hoosier at gmail.com
Wed Apr 4 14:04:32 UTC 2018


I encounter another "bad" behavior related to multiple firings of the UDev
'add' event for a given input node.

Typically on modest embedded systems, you do not want to run the exhaustive
'udevadm trigger' during the main booting sequence. That causes hundreds or
thousands of UDev nodes to be crawled and processed by udevd all during the
first moments of userspace. These overall bulk of these nodes are pretty
much irrelevant to the use-case of the device. The time spent processing
these non-essential /sys devices can easily slow down the device's progress
toward starting a UI with basic touch support and loading drivers for the
handful of essential peripherals by 10 or 15 seconds.

Instead, it works better to manually command the same UDev coldplugging
that would have been done by 'udevadm trigger', but for a very small
hand-picked set of devices rather than everything in /sys/devices. The time
savings are large. Of course, for completeness you do eventually have to
run 'udevadm trigger' so that the full set of hardware and kernel software
features are activated, but that can wait until after the main KPIs are
achieved.

This scheme generally works just fine. Manually stimulating udevd to
coldplug the specific devices you need keeps everything general:
applications that find their hardware with UDev (such as with libinput or
Weston's DRM backend) all get to rely on their usual well-tested codepaths.

But there is a snag: if a device like /dev/input/event0 has been
coldplugged once with the hands-on technique, then all the daemons that
care about it have already seen one UDev ACTION=add event for it. When the
late-running 'udevadm trigger' does its exhaustive sweep across
/sys/devices, this will cause a second ACTION=add event to be triggered for
/dev/input/event0. Currently (well, with libinput 1.1.1) this causes
libinput -- and consequently Weston -- to open a second filedescriptor
against /dev/input/event0, so that all input events are received in
duplicate. That confuses the compositor's and applications' input event
handling.

Would it be tolerable to put a patch into either libinput or Weston to
guard against double-opening the same input device? I realize that the
scheme outlined above is probably technically in violation of the expected
UDev initialization scheme, but I'm not aware of any way to suppress udevd
from broadcasting the 'add' action to all udev clients even though the
device has already been coldplugged once. It seems to me at least plausible
that the Weston stack would benefit from guarding against getting into this
bad state from receiving unexpected UDev events.

-Matt

On Wed, Apr 4, 2018 at 6:51 AM, Pekka Paalanen <ppaalanen at gmail.com> wrote:

> From: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
>
> Hi,
>
> here is a patch for a race that was troubling a distribution for an
> embedded device. The original form of this patch has been in developer
> use for months now, and it seems to work there. For this version I have
> only changed the logging and fixed a leak.
>
> I originally discussed this issue on #wayland with Peter Hutterer on
> September 22, 2017. The discussion is quoted below to refresh our
> memories.
>
> In the distribution, Weston is started by systemd, the system is not
> very CPU-powerful, and lots of things are happening during the boot,
> which may all contribute to making this race possible to lose.
>
> I've only tested briefly on my work desktop to see that Weston still
> appears to find the input devices I expect. Obviously my desktop would
> never lose the race, because there are no input devices being hotplugged
> at the same time as Weston is starting up.
>
> The timer/idle callback idea is not implemented here, and neither is the
> double-add filtering. Let me know if you require those.
>
>
> Thanks,
> pq
>
>
> < pq> whot, btw. we've looking into some fun libinput vs. udev
> device initialization race here. Apparently the device enumeration
> on libinput start-up may race with udev preparing devices at the
> same time, so the initial device enumeration for weston may see
> devices that have not had all their udev properties set yet. Do you
> recall ever fighting such issues?
>
> < pq> whot, another issue is that we may see a double-add of a
> device, first from the initial enumeration (with possibly missing
> properties) and then a second time as a hotplug event because
> libinput (correctly) listens for events before it enume existing
> devices.
>
> < whot> pq: yes, I've seen this a lot with the test suite, but never
> in real life
>
> < whot> I'm pretty sure in my case it's always a lingering udev
> device or some lingering properties
>
> < whot> e.g. a tablet has some keyboard properties set because the
> kernel re-uses the event node
>
> < whot> but that's triggered by the test suite using the path
> interface and there's bound to be a window where we can race. it
> shouldn't happen with the udev device, I think
>
> < pq> specifically, in the target device/system with touchscreens
> and weston, there are udev rules to set WL_OUTPUT on the device, but
> weston does not always see it.
>
> < pq> well, we use libinput via weston, and I don't think weston
> uses the path-based function. It's really the initial enumeration of
> input devices in libinput that has the issue.
>
> < whot> pq: a double-add is a bug, I can picture that happening with
> the current code. should be fixable
>
>  * whot mumples something about syspath comparisons to filter that
> out
>
> < whot> mumbles, even. but it's late nough that I'm also open for
> mumpling
>
> < pq> whot, nice. Yeah, let's see if we have a patch to submit or
> just a bug report, it might take a while.
>
> < whot> pq: for the missing properties I have no idea, but that
> would, if anything, be a systemd bug
>
> < pq> whot, really? What's udev_device_get_is_initialised() for
> then? Does it not apply to the initial device enumeration as done by
> libinput?
>
> < pq> whot, how does initial device enumeration work? Does it go the
> udev daemon or just look in sysfs on its own?
>
> < whot> udev_device_get_is_initialized may help but it didn't with
> the test suite
>
> < whot> but for your case, it might just because you're fighting a
> different race
>
> < whot> should be easy enough to printf that to the log in your case
> and check if it's false when it fails
>
> < pq> whot, oh yeah, this didn't feel like a lingering device issue.
>
> < whot> initial enumeration: see udev_input_add_devices in
> src/udev-seat.c
>
> < whot> basically: "get list of devices maching subsystem input,
> create udev device for each syspath in that list"
>
> < pq> whot, our current idea is to have the initial enumeration to
> ignore devices where udev_device_get_is_initialized() returns false,
> because presumably we will get the hotplug event later anyway.
>
> < pq> that would avoid any busy-loop waiting
>
> < whot> you could schedule a callback for that device's syspath
>
> < whot> takes the whole "presumably" out of the question :)
>
> < pq> you mean like an idle task to re-check it?
>
> < whot> yeah, that or a timer
>
> < whot> not sure we have idle sources in libinput right now, so a
> timer is your better option here
>
> < pq> whot, ok, sure. Thanks for the tip. :-)
>
> Nandor Han (1):
>   udev: validate input devices during cold-plug
>
>  src/udev-seat.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
>
> --
> 2.16.1
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/wayland-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/wayland-devel/attachments/20180404/bb151b66/attachment.html>


More information about the wayland-devel mailing list