<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Apr 5, 2018 at 9:28 PM, Peter Hutterer <span dir="ltr"><<a href="mailto:peter.hutterer@who-t.net" target="_blank">peter.hutterer@who-t.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On Thu, Apr 05, 2018 at 01:20:51PM +0000, Friedrich, Eugen (ADITG/ESB) wrote:<br>
> Hi Peter<br>
><br>
> Best regards<br>
><br>
> Eugen Friedrich<br>
> Engineering Software Base (ADITG/ESB)<br>
><br>
> Tel. +49 5121 49 6921<br>
><br>
> > -----Original Message-----<br>
> > From: wayland-devel [mailto:<a href="mailto:wayland-devel-">wayland-devel-</a><br>
> > <a href="mailto:bounces@lists.freedesktop.org">bounces@lists.freedesktop.org</a>] On Behalf Of Peter Hutterer<br>
> > Sent: Donnerstag, 5. April 2018 06:27<br>
> > To: Matt Hoosier<br>
> > Cc: Pekka Paalanen; wayland mailing list<br>
> > Subject: Re: [PATCH libinput 0/1] Initialization race against udev<br>
> ><br>
> > On Wed, Apr 04, 2018 at 09:04:32AM -0500, Matt Hoosier wrote:<br>
> > > I encounter another "bad" behavior related to multiple firings of the UDev<br>
> > > 'add' event for a given input node.<br>
> > ><br>
> > > Typically on modest embedded systems, you do not want to run the<br>
> > exhaustive<br>
> > > 'udevadm trigger' during the main booting sequence. That causes hundreds<br>
> > or<br>
> > > thousands of UDev nodes to be crawled and processed by udevd all during<br>
> > the<br>
> > > first moments of userspace. These overall bulk of these nodes are pretty<br>
> > > much irrelevant to the use-case of the device. The time spent processing<br>
> > > these non-essential /sys devices can easily slow down the device's<br>
> > progress<br>
> > > toward starting a UI with basic touch support and loading drivers for the<br>
> > > handful of essential peripherals by 10 or 15 seconds.<br>
> > ><br>
> > > Instead, it works better to manually command the same UDev coldplugging<br>
> > > that would have been done by 'udevadm trigger', but for a very small<br>
> > > hand-picked set of devices rather than everything in /sys/devices. The time<br>
> > > savings are large. Of course, for completeness you do eventually have to<br>
> > > run 'udevadm trigger' so that the full set of hardware and kernel software<br>
> > > features are activated, but that can wait until after the main KPIs are<br>
> > > achieved.<br>
> > ><br>
> > > This scheme generally works just fine. Manually stimulating udevd to<br>
> > > coldplug the specific devices you need keeps everything general:<br>
> > > applications that find their hardware with UDev (such as with libinput or<br>
> > > Weston's DRM backend) all get to rely on their usual well-tested<br>
> > codepaths.<br>
> > ><br>
> > > But there is a snag: if a device like /dev/input/event0 has been<br>
> > > coldplugged once with the hands-on technique, then all the daemons that<br>
> > > care about it have already seen one UDev ACTION=add event for it. When<br>
> > the<br>
> > > late-running 'udevadm trigger' does its exhaustive sweep across<br>
> > > /sys/devices, this will cause a second ACTION=add event to be triggered<br>
> > for<br>
> > > /dev/input/event0. Currently (well, with libinput 1.1.1) this causes<br>
> > > libinput -- and consequently Weston -- to open a second filedescriptor<br>
> > > against /dev/input/event0, so that all input events are received in<br>
> > > duplicate. That confuses the compositor's and applications' input event<br>
> > > handling.<br>
> > ><br>
> > > Would it be tolerable to put a patch into either libinput or Weston to<br>
> > > guard against double-opening the same input device? I realize that the<br>
> > > scheme outlined above is probably technically in violation of the expected<br>
> > > UDev initialization scheme, but I'm not aware of any way to suppress<br>
> > udevd<br>
> > > from broadcasting the 'add' action to all udev clients even though the<br>
> > > device has already been coldplugged once. It seems to me at least plausible<br>
> > > that the Weston stack would benefit from guarding against getting into this<br>
> > > bad state from receiving unexpected UDev events.<br>
> ><br>
> ><br>
> > I don't think a weston patch is likely to help you here since libinput's<br>
> > udev handling is independent of weston. but tbh, I'd rather not do this in<br>
> > libinput either. as you write, you're not really behaving like udev is<br>
> > supposed to and once we start having to deal with that the floodgates are<br>
> > open for weird patches. The code for this should be relatively<br>
> > self-contained and easy-enough to maintain, please maintain that as a<br>
> > distribution-specific patch.<br>
><br>
> [EF] but as I can see there is a race condition which can always occur in<br>
> any system if device will be added to the system after installation of the<br>
> udev monitor and before initializing already coldplugged devices.<br>
> Can we really just accept this and hope it will never happen? Or I'm missing something?<br>
<br>
</div></div>yeah, that race condition could occur but the chances are ... very slim.<br>
By the time libinput starts up, all the built-in devices are already<br>
connected and what are the chances that you plug in a USB device at that<br>
precise ms?<br>
<br>
Now, if you feel like writing patches for this you're welcome if they're not<br>
too intrusive but one problem with those patches is likely that they're<br>
almost impossible to test for the udev backend (other than by manually<br>
pausing libinput at the right time and hoping). So unless you can come up<br>
with a solution for that too, I'd rather take my chances with the race<br>
condition than maintaining untestable code that may not work correctly in<br>
the one case where we need it :)<br>
<span class=""><br>
<br>
> > especially if you're really still on 1.1.1 which came out in 2015...<br>
> ><br>
> > As for how it would work: device_added in src/udev-seat.c, you can get to<br>
> > the libinput_seat which has the device list (they're all struct<br>
> > evdev_device). You can get the fd from that and stat() it for the st_rdev<br>
> > or, simpler, add a field and strdup the device node into that struct and<br>
> > compare that.<br>
> ><br>
> > On second thought: I'm not sure how exactly you're handling the<br>
> > cold-plugging but is there a way you can add a udev rule that assigns<br>
> > LIBINPUT_IGNORE_DEVICE=1 to all input devices already handled?<br>
><br>
> [EF] Could not get the exact idea! Should we set the attribute<br>
> LIBINPUT_IGNORE_DEVICE from the libinput code?<br>
<br>
</span><span class="">Above you wrote:<br>
> Manually stimulating udevd to<br>
> coldplug the specific devices you need keeps everything general:<br></span></blockquote><div><br></div><div>I'm not certain whether this question was addressed to me or Eugen's commentary after my message.</div><div><br></div><div>In any case, when I say "manually stimulate udevd to send an 'add' event", I mean exactly what Pekka interpreted it as. 'udevadm trigger' is nothing fancy; it essentially just exhaustively crawls across /sys and writes the string "add" into each device directory in which it finds a file named /sys/.../uevent. There is no stateful interaction with udevd or anything like that.</div><div><br></div><div>So in my case, I'm just manually doing "echo add > /sys/devices/my-device-path/uevent" to shortcut the big expensive iteration that would be imposed if you tried to use 'udevadm trigger --lots-of-narrow-match-expressions'. Same effect from the perspective of interacting with the kernel or udevd though.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
<br>
</span>I don't actually know what you mean by this, so I'm not sure what the udev<br>
behaviour is in this case. But if you're holding back the<br>
trigger anyway is that you can do whatever you do for the devices, then drop<br>
a udev rule in that sets LIBINPUT_IGNORE_DEVICE, then you run the udevadm<br>
trigger. Any device that is now handled by udev will have that property<br>
assigned and will thus be ignored, including all your duplicates.<br>
<span class=""><br>
> Additional idea would be to use USEC_INITIALIZED time as unique identifier<br>
> in one boot cycle.<br>
<br>
</span>Can you expand on how you think this would work?<br>
<div class="HOEnZb"><div class="h5"><br>
Cheers,<br>
   Peter<br>
<br>
> > > On Wed, Apr 4, 2018 at 6:51 AM, Pekka Paalanen <<a href="mailto:ppaalanen@gmail.com">ppaalanen@gmail.com</a>><br>
> > wrote:<br>
> > ><br>
> > > > From: Pekka Paalanen <<a href="mailto:pekka.paalanen@collabora.co.uk">pekka.paalanen@collabora.co.<wbr>uk</a>><br>
> > > ><br>
> > > > Hi,<br>
> > > ><br>
> > > > here is a patch for a race that was troubling a distribution for an<br>
> > > > embedded device. The original form of this patch has been in developer<br>
> > > > use for months now, and it seems to work there. For this version I have<br>
> > > > only changed the logging and fixed a leak.<br>
> > > ><br>
> > > > I originally discussed this issue on #wayland with Peter Hutterer on<br>
> > > > September 22, 2017. The discussion is quoted below to refresh our<br>
> > > > memories.<br>
> > > ><br>
> > > > In the distribution, Weston is started by systemd, the system is not<br>
> > > > very CPU-powerful, and lots of things are happening during the boot,<br>
> > > > which may all contribute to making this race possible to lose.<br>
> > > ><br>
> > > > I've only tested briefly on my work desktop to see that Weston still<br>
> > > > appears to find the input devices I expect. Obviously my desktop would<br>
> > > > never lose the race, because there are no input devices being hotplugged<br>
> > > > at the same time as Weston is starting up.<br>
> > > ><br>
> > > > The timer/idle callback idea is not implemented here, and neither is the<br>
> > > > double-add filtering. Let me know if you require those.<br>
> > > ><br>
> > > ><br>
> > > > Thanks,<br>
> > > > pq<br>
> > > ><br>
> > > ><br>
> > > > < pq> whot, btw. we've looking into some fun libinput vs. udev<br>
> > > > device initialization race here. Apparently the device enumeration<br>
> > > > on libinput start-up may race with udev preparing devices at the<br>
> > > > same time, so the initial device enumeration for weston may see<br>
> > > > devices that have not had all their udev properties set yet. Do you<br>
> > > > recall ever fighting such issues?<br>
> > > ><br>
> > > > < pq> whot, another issue is that we may see a double-add of a<br>
> > > > device, first from the initial enumeration (with possibly missing<br>
> > > > properties) and then a second time as a hotplug event because<br>
> > > > libinput (correctly) listens for events before it enume existing<br>
> > > > devices.<br>
> > > ><br>
> > > > < whot> pq: yes, I've seen this a lot with the test suite, but never<br>
> > > > in real life<br>
> > > ><br>
> > > > < whot> I'm pretty sure in my case it's always a lingering udev<br>
> > > > device or some lingering properties<br>
> > > ><br>
> > > > < whot> e.g. a tablet has some keyboard properties set because the<br>
> > > > kernel re-uses the event node<br>
> > > ><br>
> > > > < whot> but that's triggered by the test suite using the path<br>
> > > > interface and there's bound to be a window where we can race. it<br>
> > > > shouldn't happen with the udev device, I think<br>
> > > ><br>
> > > > < pq> specifically, in the target device/system with touchscreens<br>
> > > > and weston, there are udev rules to set WL_OUTPUT on the device, but<br>
> > > > weston does not always see it.<br>
> > > ><br>
> > > > < pq> well, we use libinput via weston, and I don't think weston<br>
> > > > uses the path-based function. It's really the initial enumeration of<br>
> > > > input devices in libinput that has the issue.<br>
> > > ><br>
> > > > < whot> pq: a double-add is a bug, I can picture that happening with<br>
> > > > the current code. should be fixable<br>
> > > ><br>
> > > >  * whot mumples something about syspath comparisons to filter that<br>
> > > > out<br>
> > > ><br>
> > > > < whot> mumbles, even. but it's late nough that I'm also open for<br>
> > > > mumpling<br>
> > > ><br>
> > > > < pq> whot, nice. Yeah, let's see if we have a patch to submit or<br>
> > > > just a bug report, it might take a while.<br>
> > > ><br>
> > > > < whot> pq: for the missing properties I have no idea, but that<br>
> > > > would, if anything, be a systemd bug<br>
> > > ><br>
> > > > < pq> whot, really? What's udev_device_get_is_<wbr>initialised() for<br>
> > > > then? Does it not apply to the initial device enumeration as done by<br>
> > > > libinput?<br>
> > > ><br>
> > > > < pq> whot, how does initial device enumeration work? Does it go the<br>
> > > > udev daemon or just look in sysfs on its own?<br>
> > > ><br>
> > > > < whot> udev_device_get_is_initialized may help but it didn't with<br>
> > > > the test suite<br>
> > > ><br>
> > > > < whot> but for your case, it might just because you're fighting a<br>
> > > > different race<br>
> > > ><br>
> > > > < whot> should be easy enough to printf that to the log in your case<br>
> > > > and check if it's false when it fails<br>
> > > ><br>
> > > > < pq> whot, oh yeah, this didn't feel like a lingering device issue.<br>
> > > ><br>
> > > > < whot> initial enumeration: see udev_input_add_devices in<br>
> > > > src/udev-seat.c<br>
> > > ><br>
> > > > < whot> basically: "get list of devices maching subsystem input,<br>
> > > > create udev device for each syspath in that list"<br>
> > > ><br>
> > > > < pq> whot, our current idea is to have the initial enumeration to<br>
> > > > ignore devices where udev_device_get_is_<wbr>initialized() returns false,<br>
> > > > because presumably we will get the hotplug event later anyway.<br>
> > > ><br>
> > > > < pq> that would avoid any busy-loop waiting<br>
> > > ><br>
> > > > < whot> you could schedule a callback for that device's syspath<br>
> > > ><br>
> > > > < whot> takes the whole "presumably" out of the question :)<br>
> > > ><br>
> > > > < pq> you mean like an idle task to re-check it?<br>
> > > ><br>
> > > > < whot> yeah, that or a timer<br>
> > > ><br>
> > > > < whot> not sure we have idle sources in libinput right now, so a<br>
> > > > timer is your better option here<br>
> > > ><br>
> > > > < pq> whot, ok, sure. Thanks for the tip. :-)<br>
> > > ><br>
> > > > Nandor Han (1):<br>
> > > >   udev: validate input devices during cold-plug<br>
> > > ><br>
> > > >  src/udev-seat.c | 11 +++++++++++<br>
> > > >  1 file changed, 11 insertions(+)<br>
> > > ><br>
> > > > --<br>
> > > > 2.16.1<br>
> > > ><br>
> > > > ______________________________<wbr>_________________<br>
> > > > wayland-devel mailing list<br>
> > > > <a href="mailto:wayland-devel@lists.freedesktop.org">wayland-devel@lists.<wbr>freedesktop.org</a><br>
> > > > <a href="https://lists.freedesktop.org/mailman/listinfo/wayland-devel" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/wayland-devel</a><br>
> > > ><br>
> ><br>
> > > ______________________________<wbr>_________________<br>
> > > wayland-devel mailing list<br>
> > > <a href="mailto:wayland-devel@lists.freedesktop.org">wayland-devel@lists.<wbr>freedesktop.org</a><br>
> > > <a href="https://lists.freedesktop.org/mailman/listinfo/wayland-devel" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/wayland-devel</a><br>
> ><br>
> > ______________________________<wbr>_________________<br>
> > wayland-devel mailing list<br>
> > <a href="mailto:wayland-devel@lists.freedesktop.org">wayland-devel@lists.<wbr>freedesktop.org</a><br>
> > <a href="https://lists.freedesktop.org/mailman/listinfo/wayland-devel" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/wayland-devel</a><br>
><br>
</div></div></blockquote></div><br></div></div>