Repository navigation
Conversation
The switch to libudev made removal notifications reliable in the common case, but the client still relies on them exclusively. The kernel hangs up the evdev descriptor as soon as the device is unregistered, while the udev remove event only arrives after udevd has processed it. Until then (or forever, if the event is lost to a monitor socket overflow) the descriptor stays POLLERR | POLLHUP, libevdev returns -ENODEV, and poll() ignores it, pinning a core and starving event relay for other devices. - poll(): treat -ENODEV as device removal - evdevDeviceAdded(): drop any device still held for the path, since a new node there means the remove event for the old one was missed - tryAddEvdevDevice(): never hold two devices for one path, which the retry queue could otherwise cause - evdevDeviceRemoved(): also drop the path from the retry queue Reproducible by pausing udevd (udevadm control --stop-exec-queue) and disconnecting a grabbed device. Fixes InputActions/discussions#492
When libinput keeps rejecting a device's event injection device, the retry timer gave up by erasing the device from m_devices without calling removeDevice(). InputBackend kept the freed pointer in its device list and event handler chain, so anything iterating devices afterwards (e.g. `inputactions devices list`, keyboard modifier queries) read freed memory. Remove the device through removeDeviceAt() like every other path, and log why it was dropped.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two commits to improve overall stability when adding/removing devices:
client/input: remove dead devices on read failure (fixes InputActions/discussions#492)
poll(): remove the device on-ENODEVto avoid the client spinning at 100% CPU until udev's "remove" event arrives.evdevDeviceAdded(),tryAddEvdevDevice(): never hold two devices for one path.evdevDeviceRemoved(): also take the path out of the retry queue.client/input: unregister devices dropped by the retry timer
removeDeviceAt(), also in the retry timer. Before, it freed the device without unregistering it, leading to a heap-use-after-free.