Bug 71878

Summary: Touch screen usage eventually results in X server unresponsive to keyboard input
Product: xorg Reporter: Ben Gamari <bgamari>
Component: Server/Input/CoreAssignee: Xorg Project Team <xorg-team>
Status: RESOLVED MOVED QA Contact: Xorg Project Team <xorg-team>
Severity: major    
Priority: medium CC: peter.hutterer
Version: git   
Hardware: Other   
OS: All   
Whiteboard:
i915 platform: i915 features:
Attachments:
Description Flags
Full Xorg.log
none
A quick patch implementing the describing fix and/or workaround none

Description Ben Gamari 2013-11-21 15:08:23 UTC
Created attachment 89592 [details]
Full Xorg.log

This appears to have similar root cause to #66720.

I use XMonad on a Dell Latitude E7440. After a few dozen events on the touchscreen I find that the keyboard will cease to respond. This is accompanied by errors in Xorg.0.log,

[  9794.788] (EE) BUG: triggered 'if (ti->listeners[0].type != LISTENER_GRAB && ti->listeners[0].type != LISTENER_POINTER_GRAB)'
[  9794.789] (EE) BUG: ../../Xi/exevents.c:1044 in ActivateEarlyAccept()
[  9794.789] (EE) 
[  9794.789] (EE) Backtrace:
[  9794.789] (EE) 0: /usr/bin/X (xorg_backtrace+0x3d) [0x7f68034634fd]
[  9794.789] (EE) 1: /usr/bin/X (0x7f68032c1000+0x132072) [0x7f68033f3072]
[  9794.790] (EE) 2: /usr/bin/X (0x7f68032c1000+0x1336bb) [0x7f68033f46bb]
[  9794.790] (EE) 3: /usr/bin/X (0x7f68032c1000+0x135e02) [0x7f68033f6e02]
[  9794.790] (EE) 4: /usr/bin/X (0x7f68032c1000+0x156f46) [0x7f6803417f46]
[  9794.791] (EE) 5: /usr/bin/X (mieqProcessDeviceEvent+0x1cd) [0x7f680344581d]
[  9794.791] (EE) 6: /usr/bin/X (mieqProcessInputEvents+0xf7) [0x7f6803445937]
[  9794.791] (EE) 7: /usr/bin/X (ProcessInputEvents+0x9) [0x7f6803352f79]
[  9794.791] (EE) 8: /usr/bin/X (0x7f68032c1000+0x54f12) [0x7f6803315f12]
[  9794.792] (EE) 9: /usr/bin/X (0x7inaf68032c1000+0x4472a) [0x7f680330572a]
[  9794.792] (EE) 10: /lib/x86_64-linux-gnu/libc.so.6 (__libc_start_main+0xf5) [0x7f6800ffcde5]
[  9794.792] (EE) 11: /usr/bin/X (0x7f68032c1000+0x44a6f) [0x7f6803305a6f]

I originally observed this on Ubuntu Saucy's 1.14.3 xserver. To confirm this wasn't Ubuntu-specific I built a package from the 1.14.4 tag and found similar behavior. It seems that #66720 fixed at least one issue similar to this. I haven't carefully tested this but it may be that the bug is less likely to occur while using Unity instead of XMonad.
Comment 1 Ben Gamari 2013-11-21 15:18:39 UTC
Also, sometimes after using the touch device instead of killing keyboard input altogether, it will simply pause it until the next mouse click. For instance,

1) Type on keyboard, see text produced
2) Use touch screen
3) Type on keyboard, no text is produced
4) Click touchpad button, characters typed suddenly appear
Comment 2 Ben Gamari 2013-11-21 23:37:42 UTC
It seems that this isn't reproducible with Unity at all. Any idea what XMonad might be doing differently?

Regardless, this should probably still be considered a bug: even a misbehaving (or simply touch unaware) window manager shouldn't be able to kill keyboard input.
Comment 3 Ben Gamari 2013-11-22 02:27:23 UTC
The problem might be the following: `DeliverTouchBeginEvent` tries to
deliver an event to a listener of type `LISTENER_POINTER_REGULAR`,
taking the following `if` branch,

    if (listener->type == LISTENER_POINTER_REGULAR ||
        listener->type == LISTENER_POINTER_GRAB) {
        rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
                                       grab, xi2mask);
        if (rc == Success) {
            listener->state = LISTENER_IS_OWNER;
            /* async grabs cannot replay, so automatically accept this touch */
            if (dev->deviceGrab.grab &&
                dev->deviceGrab.fromPassiveGrab &&
                dev->deviceGrab.grab->pointerMode == GrabModeAsync)
                ActivateEarlyAccept(dev, ti);
        }
        goto out;
    }

`DeliverTouchEmulatedEvent` succeeds.  The `deviceGrab` meets all
three of the conditions of the inner `if`, enters
`ActivateEarlyAccept` which then fails due to,


    BUG_RETURN(ti->listeners[0].type != LISTENER_GRAB &&
               ti->listeners[0].type != LISTENER_POINTER_GRAB);

That is, despite `listener->type == LISTENER_POINTER_REGULAR`. With my
non-existent knowledge of XINPUT, it seems like the solution here
might be to only `ActivateEarlyAccept` when `listener->type ==
LISTENER_POINTER_GRAB`.
Comment 4 Ben Gamari 2013-11-22 02:31:53 UTC
Created attachment 89614 [details] [review]
A quick patch implementing the describing fix and/or workaround

Here is a patch which implements the fix or workaround described above. It seems to prevent touch events from taking down keyboard input. That being said, the pause issue described in Comment 1 seems to still occur.
Comment 5 Ben Gamari 2013-11-22 03:01:31 UTC
Sadly it seems like occassionally the keyboard queue freeze is irrecoverable, even aftering throwing in more input events from other devices. I've only seen this once so far after a touch drag. Notably, one of the windows on-screen at the time of the drag (perhaps the window with focus at that moment) stopped redrawing after the incident.
Comment 6 Ben Gamari 2013-11-22 03:04:06 UTC
I just had a keyboard pause incident produce a BUG:

[ 36800.740] (EE) BUG: triggered 'if (!(event->device_event.flags & (1 << 5)))'
[ 36800.740] (EE) BUG: ../../dix/touch.c:644 in TouchConvertToPointerEvent()
[ 36800.740] (EE) Non-emulating touch event
Comment 7 Ben Gamari 2013-11-22 13:27:20 UTC
It seems that dragging across multiple windows is a good way to trigger the keyboard pauses.
Comment 8 Ben Gamari 2013-11-22 13:28:57 UTC
I've followed the dropped key events into exevent.c. We make it
through,

  ProcessKeyboardEvent (xkb/xkbPrKeyEv.c)
  ProcessOtherEvent (Xi/exevents.c)
  ProcessDeviceEvent (Xi/exevents.c)
  DeliverFocusedEvent (Xi/exevents.c)

Then `DeliverFocusedEvent` finds that `keydb->focus->win ==
PointerRootWin`. This causes it to try delivering the events with
`DeliverDeviceEvents` to "the Window underneath the sprite" but it
fails,

  DeliverDeviceEvents (dix/events.c)

In the delivery loop,

    mask == EVENT_CORE_MASK
    IsMaster(dev) == 0
    dev->coreEvents == 4

therefore nothing gets delivered. I suspect the problem is the lack of
a focused window. `DeliverFocusedEvent` should be falling through the initial
checks to the "just deliver it to the focus window" behavior. Why is there no focused window?
Comment 9 Ben Gamari 2013-12-01 04:31:23 UTC
Some useful discussion of this issue has happened on the list[1].

[1] http://lists.x.org/archives/xorg/2013-November/056209.html
Comment 10 Peter Hutterer 2013-12-02 23:34:36 UTC
http://patchwork.freedesktop.org/patch/16209/
Comment 11 GitLab Migration User 2018-12-17 17:28:11 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/xorg/xserver/issues/593.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.