evdev: log a bug if releasing a key fails, but don't loop forever
authorPeter Hutterer <peter.hutterer@who-t.net>
Tue, 19 May 2015 04:44:16 +0000 (14:44 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Thu, 21 May 2015 11:41:46 +0000 (21:41 +1000)
If a physical button is down but releasing said button doesn't actually
release it, we loop endlessly. Detect that and log a bug instead.

Reproducible: trigger a tap-n-drag on a touchpad device, then remove it.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Tested-by: Benjamin Tissoires <benjamin.tissoires@gmail.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
src/evdev.c

index 5f1a943..90c4e2c 100644 (file)
@@ -2330,6 +2330,9 @@ release_pressed_keys(struct evdev_device *device)
        for (code = 0; code < KEY_CNT; code++) {
                int count = get_key_down_count(device, code);
 
+               if (count == 0)
+                       continue;
+
                if (count > 1) {
                        log_bug_libinput(libinput,
                                         "Key %d is down %d times.\n",
@@ -2337,25 +2340,31 @@ release_pressed_keys(struct evdev_device *device)
                                         count);
                }
 
-               while (get_key_down_count(device, code) > 0) {
-                       switch (get_key_type(code)) {
-                       case EVDEV_KEY_TYPE_NONE:
-                               break;
-                       case EVDEV_KEY_TYPE_KEY:
-                               evdev_keyboard_notify_key(
-                                       device,
-                                       time,
-                                       code,
-                                       LIBINPUT_KEY_STATE_RELEASED);
-                               break;
-                       case EVDEV_KEY_TYPE_BUTTON:
-                               evdev_pointer_notify_physical_button(
-                                       device,
-                                       time,
-                                       evdev_to_left_handed(device, code),
-                                       LIBINPUT_BUTTON_STATE_RELEASED);
-                               break;
-                       }
+               switch (get_key_type(code)) {
+               case EVDEV_KEY_TYPE_NONE:
+                       break;
+               case EVDEV_KEY_TYPE_KEY:
+                       evdev_keyboard_notify_key(
+                               device,
+                               time,
+                               code,
+                               LIBINPUT_KEY_STATE_RELEASED);
+                       break;
+               case EVDEV_KEY_TYPE_BUTTON:
+                       evdev_pointer_notify_physical_button(
+                               device,
+                               time,
+                               evdev_to_left_handed(device, code),
+                               LIBINPUT_BUTTON_STATE_RELEASED);
+                       break;
+               }
+
+               count = get_key_down_count(device, code);
+               if (count != 0) {
+                       log_bug_libinput(libinput,
+                                        "Releasing key %d failed.\n",
+                                        code);
+                       break;
                }
        }
 }