Ungrabbing slave keyboards causes X to crash
It seems that attempting to ungrab an Xinput slave device while a different VT is active causes X to crash.
Compiling and running test.c
and then switching VTs before it terminates causes X to crash with the following backtrace on my machine.
X.Org X Server 1.20.4
...
[1076359.609] (EE) Backtrace:
[1076359.610] (EE) 0: /usr/lib/xorg/Xorg (OsLookupColor+0x139) [0x55555a6932c9]
[1076359.610] (EE) 1: /lib/x86_64-linux-gnu/libpthread.so.0 (funlockfile+0x50) [0x7f5231d3077f]
[1076359.610] (EE) 2: /usr/lib/xorg/Xorg (InitCallbackManager+0x1bb8) [0x55555a53ce18]
[1076359.610] (EE) 3: /usr/lib/xorg/Xorg (DeliverEvents+0x102d) [0x55555a54609d]
[1076359.610] (EE) 4: /usr/lib/xorg/Xorg (AssignTypeAndName+0x6e7c) [0x55555a62c74c]
[1076359.610] (EE) 5: /usr/lib/xorg/Xorg (SendErrorToClient+0x35e) [0x55555a5349ce]
[1076359.610] (EE) 6: /usr/lib/xorg/Xorg (InitFon[test.c](/uploads/189b2af7dea4b8d947e3d323993d612e/test.c)ts+0x3b6) [0x55555a538956]
[1076359.611] (EE) 7: /lib/x86_64-linux-gnu/libc.so.6 (__libc_start_main+0xeb)
[1076359.611] (EE) 8: /usr/lib/xorg/Xorg (_start+0x2a) [0x55555a52267a]
test.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/time.h>
#include <ctype.h>
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/extensions/XTest.h>
#include <X11/extensions/XInput2.h>
#include <assert.h>
Display *dpy;
void grab(int devid)
{
size_t i;
XIEventMask mask;
mask.deviceid = XIAllDevices;
mask.mask_len = XIMaskLen(XI_LASTEVENT);
mask.mask = calloc(mask.mask_len, sizeof(char));
XISetMask(mask.mask, XI_KeyPress);
XISetMask(mask.mask, XI_KeyRelease);
if(XIGrabDevice(dpy, devid,
DefaultRootWindow(dpy),
CurrentTime,
None,
GrabModeAsync,
GrabModeAsync,
False, &mask)) {
fprintf(stderr, "FATAL: Failed to grab keyboard\n");
exit(-1);
}
XSync(dpy, False);
}
static int get_dev_id()
{
int i, n;
XIDeviceInfo* devs = XIQueryDevice(dpy, XIAllDevices, &n);
for (i = 0; i < n; i++) {
if (devs[i].use == XISlaveKeyboard &&
!strstr(devs[i].name, "XTEST")) {
printf("Grabbing %s\n", devs[i].name);
return devs[i].deviceid;
}
}
}
int main()
{
int i;
dpy = XOpenDisplay(NULL);
int id = get_dev_id();
grab(id);
sleep(3); //Switch vts here, observe crash
XIUngrabDevice(dpy, id, CurrentTime);
XSync(dpy, False);
}