Make EvdevRead() return errors to the caller

Errors during read() in EvdevRead() are not passed back to the caller.
This is problematic for level-triggered IO polling, because permanent
errors (such as device removal) are not detected and we will continue to
poll the device forever without handling the error.

This manifests itself as the device polling thread spinning, and non-IO
tasks (device hotplug, feedback collection) do not make progress because
MessagePumpLibevent never yields until there's no work to do.

xf86-input-cmt expects errno values to be returned from EvdevRead() (even
though it wasn't doing so), so return the errno value upon failure.
Temporary errors still return success; otherwise we also need to patch
the call site.

TEST=Change chrome to delay unplug events to make the bug reproduce
     easily, then remove a mouse from the system. Without fix, device
     thread spins at 100% CPU and hotplug stops making progress. With
     fix, the error is detected and the libevent watcher gets cancelled.

Change-Id: I5c968c89f8bed72ba48124313136605754599c88
Reviewed-by: Kevin Schoedel <>
Reviewed-by: Alex Sakhartchouk <>
Tested-by: Michael Spang <>
Commit-Queue: Matthew Yuan <>
diff --git a/src/libevdev.c b/src/libevdev.c
index 589cb28..e920a02 100644
--- a/src/libevdev.c
+++ b/src/libevdev.c
@@ -56,12 +56,16 @@
   EventStatePtr evstate = evdev->evstate;
   int i;
   int len;
+  int status = Success;
   bool sync_evdev_state = false;
   do {
     len = read(evdev->fd, &ev, sizeof(ev));
-    if (len <= 0)
+    if (len < 0) {
+      if (errno != EINTR && errno != EAGAIN)
+        status = errno;
+    }
     /* Read as many whole struct input_event objects as we can into the
        circular buffer */
@@ -97,7 +101,7 @@
   if (sync_evdev_state)
-  return Success;
+  return status;
 int EvdevProbe(EvdevPtr device) {