[PATCH xserver] inputthread: Re-add fd to the inputThreadInfo->fds pollfd set when re-added

Hans de Goede hdegoede at redhat.com
Wed Oct 12 14:55:08 UTC 2016


If the following call sequence happens:
1) InputThreadUnregisterDev(fd)
2) close(fd)
3) fd = open(...) /* returns same fd as just closed */
4) InputThreadRegisterDev(fd, ...)

Without InputThreadDoWork(); running in the mean time, then we would
keep the closed fd in the inputThreadInfo->fds pollfd set, rather then
removing it and adding the new one, causing some devices to not work
after a vt-switch when using xf86-input-evdev.

BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=97880
Reported-and-tested-by: Mihail Konev <k.mvc at ya.ru>
Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
 os/inputthread.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/os/inputthread.c b/os/inputthread.c
index ab1559f..c20c21c 100644
--- a/os/inputthread.c
+++ b/os/inputthread.c
@@ -49,6 +49,7 @@ Bool InputThreadEnable = TRUE;
 
 typedef enum _InputDeviceState {
     device_state_added,
+    device_state_re_added,
     device_state_running,
     device_state_removed
 } InputDeviceState;
@@ -206,8 +207,8 @@ InputThreadRegisterDev(int fd,
     if (dev) {
         dev->readInputProc = readInputProc;
         dev->readInputArgs = readInputArgs;
-        /* Override possible unhandled state == device_state_removed */
-        dev->state = device_state_running;
+        if (dev->state == device_state_removed)
+            dev->state = device_state_re_added;
     } else {
         dev = calloc(1, sizeof(InputThreadDevice));
         if (dev == NULL) {
@@ -344,6 +345,16 @@ InputThreadDoWork(void *arg)
                     ospoll_listen(inputThreadInfo->fds, dev->fd, X_NOTIFY_READ);
                     dev->state = device_state_running;
                     break;
+                case device_state_re_added:
+                    /* Device might use a new fd with the same number */
+                    ospoll_remove(inputThreadInfo->fds, dev->fd);
+                    ospoll_add(inputThreadInfo->fds, dev->fd,
+                               ospoll_trigger_level,
+                               InputReady,
+                               dev);
+                    ospoll_listen(inputThreadInfo->fds, dev->fd, X_NOTIFY_READ);
+                    dev->state = device_state_running;
+                    break;
                 case device_state_running:
                     break;
                 case device_state_removed:
-- 
2.9.3



More information about the xorg-devel mailing list