From 9b9bfeb02d43b4f6d2946b8ba3455b9062dd1aac Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Mar 2026 02:09:42 +0000 Subject: [PATCH] Fix XI_BadDevice crash on USB device disconnect (#9723) When a USB HID device (keyboard/mouse) is disconnected, X11 fires an XI_HierarchyChanged event, which triggers read_xi_scroll_devices(). That function calls XIGetProperty() on devices from XIQueryDevice(). There is a race condition: if a device is removed between these calls, X11 generates an XI_BadDevice error. Without a custom error handler, the default X11 handler calls exit(), killing kitty. Fix: wrap the device query loop in read_xi_scroll_devices() with _glfwGrabErrorHandlerX11() / _glfwReleaseErrorHandlerX11() so that any XI_BadDevice error is captured by kitty's own handler rather than the default fatal one. Fixes #9723 Fixes #9724 --- glfw/x11_init.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/glfw/x11_init.c b/glfw/x11_init.c index fd09fec56..44385df0e 100644 --- a/glfw/x11_init.c +++ b/glfw/x11_init.c @@ -156,8 +156,11 @@ read_xi_scroll_devices(void) { if (!xi.available || xi.major < 2 || (xi.major == 2 && xi.minor < 1) || !xi.LIBINPUT_SCROLL_METHOD_ENABLED) return; #undef xi int deviceCount; + // Grab the error handler to prevent XI_BadDevice errors from killing kitty + // when a device is removed between XIQueryDevice and XIGetProperty calls. + _glfwGrabErrorHandlerX11(); XIDeviceInfo* devices = XIQueryDevice(_glfw.x11.display, XIAllDevices, &deviceCount); - if (!devices) return; + if (!devices) { _glfwReleaseErrorHandlerX11(); return; } for (int i = 0; i < deviceCount; i++) { XIDeviceInfo* device = &devices[i]; if (device->use == XIMasterPointer) _glfw.x11.xi.master_pointer_id = device->deviceid; @@ -251,6 +254,7 @@ read_xi_scroll_devices(void) { } } XIFreeDeviceInfo(devices); + _glfwReleaseErrorHandlerX11(); } // Look for and initialize supported X11 extensions