问题描述
我的单线程窗口管理器中有一个不可重复的,未知来源的错误,该错误很少发生(每2-3周一次)。发生某些事情导致我无法输入键盘。鼠标事件仍然得到正确处理,因此我知道事件循环仍在运行,但不再触发按键事件。实际上,密钥已不再被抓住。当我按XCB_MOD_MASK_4 + 2切换到桌面2时,2将显示在当前具有输入焦点的文本编辑器或终端中,而不是被窗口管理器抓取。我以为可能与xcb_allow_events有关,因此我可以通过IPC执行这三个测试(从窗口管理器中,从外部进程接收到cmd):
if (strcmp(cmd,"test0")==0)
xcb_allow_events(wm.conn,XCB_ALLOW_ASYNC_KEYBOARD,XCB_CURRENT_TIME);
else if (strcmp(cmd,"test1")==0)
xcb_allow_events(wm.conn,XCB_ALLOW_SYNC_KEYBOARD,"test2")==0)
keyboard();
void keyboard()
{
int i,m,k;
xcb_void_cookie_t cookie;
spawn("/usr/bin/xmodmap -e 'keycode 108 = Super_L'");
spawn("/usr/bin/xmodmap -e 'remove mod1 = Super_L'");
for (i=0; i<LENGTH(key_bindings); i++)
{
m = key_bindings[i].mod;
k = keysc(key_bindings[i].keysym);
info("grabbing key: %s (%d),mod: %d",key_bindings[i].keysym,k,m);
cookie = xcb_grab_key_checked(wm.conn,wm.root,XCB_GRAB_MODE_ASYNC,XCB_GRAB_MODE_ASYNC);
if (xcb_request_check (wm.conn,cookie))
error("can't grab key");
}
}
这些测试均无帮助。我知道键盘功能可以正常运行,因为它可以在窗口管理器启动时运行。我还可以在日志文件中看到,通过IPC提示时,键盘功能中的按键抓取实际上正在执行(无错误)。当前的解决方法是将sigterm发送到窗口管理器进程,然后重新启动wm。到那时,一切都会恢复正常。
我正在寻找可能有助于追查此问题根源或在问题发生后纠正问题的技术(另一项测试)。不幸的是,由于我不知道这个问题的根源或触发它的原因,所以我无法制作一个简单的测试用例进行演示。顺便说一句,发生这种情况时,我检查了日志文件,但没有发现导致此问题的任何模式。每个功能都会在入口和出口记录一个条目。
解决方法
您可以尝试在X服务器上使用strace
或perf trace
来查看关键事件在做什么。应该从/dev/input
中的某个位置读取它们,并将它们作为事件发送给已连接的客户端。
如果它没有向您发送事件,那么您可能需要挖掘其内部状态,也许是通过构建调试服务器并使用GDB连接到它,以了解为什么它没有发送这些事件。
但是,如果它将事件发送到您的WM,则它们会在库堆栈中的某个位置丢失。