Package: emacs;
Reported by: Maze <maze <at> pkbd.org>
Date: Sun, 24 Apr 2022 17:35:02 UTC
Severity: normal
Found in version 27.2
Done: Po Lu <luangruo <at> yahoo.com>
Bug is archived. No further changes may be made.
View this message in rfc822 format
From: Maze <maze <at> pkbd.org> To: 55094 <at> debbugs.gnu.org Subject: bug#55094: 27.2; XELB under EXWM stops processing all keyboard events Date: Mon, 25 Apr 2022 01:16:49 +0800
Sorry if this is not be the right place to report: this is a bug of GNU ELPA package XELB running under EXWM, and not a bug of vanilla emacs. However it seems the official place to report EXWM is on Github, and, unless I missed something, it won't let me report a bug there unless I create a github account, which I won't. Description: after hitting a key from the number row, EXWM acting as the X Window Manager stops processing all keyboard input. Emacs and all other graphical programs lose keyboard input. For me this happens always after hitting any key from the numbers row of my keyboard. Specifics may very possibly vary for other users but my informed guess is that the risk is existing for all keyboard configurations, as I will try to explain. Cause: a backtrace is generated showing that an array of xkb keytypes was referenced out of its range in the method xcb:keysyms:keycode->keysym. I included this backtrace at the end of this message. This situation develops for the following reason: When initializing EXWM, XELB creates a keyboard representation including 2 arrays for keysyms and keytypes. After I hit a first key and start using the WM, XELB processes an XkbNewKeyBoardNotify event. XELB reacts to this event by creating a new keysyms array without creating a new keytypes array. Because the original keyboard had 28 keytypes but the new keyboard has 29 keytypes in Xkb, and since my number row keys get associated to the highest index keytype of the new keyboard, this causes the legacy keytypes array to be accessed out of range by one index after I hit one of the number row keys. Solution: I propose a patch. I'm not sure it's absolutely the best thing to do but it is tested on my configuration and I think it probably should not cause breaks for other users: calling the method xcb:keysyms:-update-keytypes with correct parameters is in effect retrieving information from Xkb and putting XELB in sync. My guess is that the logic which drives this condition of xcb:keysyms:-update-keycodes to be called alone without calling xcb:keysyms:-update-keytype is not sanely selecting only cases where it would be a good idea to skip the call... At this stage of my understanding, calling both methods has to be safe in all cases, and solves the severe crash of the WM that I experience. * in method xcb:keysyms:-on-NewKeyboardNotify, update keytypes of new keyboard in order to prevent the WM from crashing when processing keycodes diff --git a/xcb-keysyms.el b/xcb-keysyms.el index af4f97b..2b7f89f 100644 --- a/xcb-keysyms.el +++ b/xcb-keysyms.el @@ -161,6 +161,7 @@ This method must be called before using any other method in this module." (setq device (xcb:-get-extra-plist obj 'keysyms deviceID)) (when (and device (not (slot-value device 'updated))) + (xcb:keysyms:-update-keytypes obj deviceID) (xcb:keysyms:-update-keycodes obj deviceID) (when (= deviceID device-id) (setq updated t) Below is the backtrace that I obtained when I hit a key from the numbers row while EXWM is managing X windows: window-list xcb-debug:buffer t ...))) (while --dolist-tail-- (let (...) (if ... ...) (setq --dolist-tail-- ...)))) (save-excursion (goto-char (point-max)) (let ((standard-output ...)) (backtrace))) (let ((--dolist-tail-- windows-eob)) (while --dolist-tail-- (let (...) (set-window-point w ...) (setq --dolist-tail-- ...)))))))(error (args-out-of-range [#<xcb:xkb:KeyType xcb:xkb:KeyType-d97a0c> #<xcb:xkb:KeyType xcb:xkb:KeyType-d97a20> #<xcb:xkb:KeyType xcb:xkb:KeyType-c84518> #<xcb:xkb:KeyType xcb:xkb:KeyType-ca101c> #<xcb:xkb:KeyType xcb:xkb:KeyType-c4e190> #<xcb:xkb:KeyType xcb:xkb:KeyType-cbc07c> #<xcb:xkb:KeyType xcb:xkb:KeyType-c4e150> #<xcb:xkb:KeyType xcb:xkb:KeyType-c8d79c> #<xcb:xkb:KeyType xcb:xkb:KeyType-c96104> #<xcb:xkb:KeyType xcb:xkb:KeyType-c9207c> #<xcb:xkb:KeyType xcb:xkb:KeyType-d0c5b8> #<xcb:xkb:KeyType xcb:xkb:KeyType-d9620c> #<xcb:xkb:KeyType xcb:xkb:KeyType-d96220> #<xcb:xkb:KeyType xcb:xkb:KeyType-c8d774> #<xcb:xkb:KeyType xcb:xkb:KeyType-c14764> #<xcb:xkb:KeyType xcb:xkb:KeyType-be9f50> #<xcb:xkb:KeyType xcb:xkb:KeyType-ce2990> #<xcb:xkb:KeyType xcb:xkb:KeyType-c149b0> #<xcb:xkb:KeyType xcb:xkb:KeyType-c142dc> #<xcb:xkb:KeyType xcb:xkb:KeyType-cbbd98> #<xcb:xkb:KeyType xcb:xkb:KeyType-d97430> #<xcb:xkb:KeyType xcb:xkb:KeyType-be8d74> #<xcb:xkb:KeyType xcb:xkb:KeyType-be8e00> #<xcb:xkb:KeyType xcb:xkb:KeyType-b9aa80> #<xcb:xkb:KeyType xcb:xkb:KeyType-c4e424> #<xcb:xkb:KeyType xcb:xkb:KeyType-cde514> #<xcb:xkb:KeyType xcb:xkb:KeyType-c37118> #<xcb:xkb:KeyType xcb:xkb:KeyType-d11e10>] 28)) aref([#<xcb:xkb:KeyType xcb:xkb:KeyType-d97a0c> #<xcb:xkb:KeyType xcb:xkb:KeyType-d97a20> #<xcb:xkb:KeyType xcb:xkb:KeyType-c84518> #<xcb:xkb:KeyType xcb:xkb:KeyType-ca101c> #<xcb:xkb:KeyType xcb:xkb:KeyType-c4e190> #<xcb:xkb:KeyType xcb:xkb:KeyType-cbc07c> #<xcb:xkb:KeyType xcb:xkb:KeyType-c4e150> #<xcb:xkb:KeyType xcb:xkb:KeyType-c8d79c> #<xcb:xkb:KeyType xcb:xkb:KeyType-c96104> #<xcb:xkb:KeyType xcb:xkb:KeyType-c9207c> #<xcb:xkb:KeyType xcb:xkb:KeyType-d0c5b8> #<xcb:xkb:KeyType xcb:xkb:KeyType-d9620c> #<xcb:xkb:KeyType xcb:xkb:KeyType-d96220> #<xcb:xkb:KeyType xcb:xkb:KeyType-c8d774> #<xcb:xkb:KeyType xcb:xkb:KeyType-c14764> #<xcb:xkb:KeyType xcb:xkb:KeyType-be9f50> #<xcb:xkb:KeyType xcb:xkb:KeyType-ce2990> #<xcb:xkb:KeyType xcb:xkb:KeyType-c149b0> #<xcb:xkb:KeyType xcb:xkb:KeyType-c142dc> #<xcb:xkb:KeyType xcb:xkb:KeyType-cbbd98> #<xcb:xkb:KeyType xcb:xkb:KeyType-d97430> #<xcb:xkb:KeyType xcb:xkb:KeyType-be8d74> #<xcb:xkb:KeyType xcb:xkb:KeyType-be8e00> #<xcb:xkb:KeyType xcb:xkb:KeyType-b9aa80> #<xcb:xkb:KeyType xcb:xkb:KeyType-c4e424> #<xcb:xkb:KeyType xcb:xkb:KeyType-cde514> #<xcb:xkb:KeyType xcb:xkb:KeyType-c37118> #<xcb:xkb:KeyType xcb:xkb:KeyType-d11e10>] 28) (setq keytype (aref (slot-value object 'keytypes) (elt (slot-value keycode 'kt-index) group))) (catch 'return (if (<= (slot-value object 'min-keycode) keycode (slot-value object 'max-keycode)) nil (throw 'return '(0 . 0))) (setq keycode (aref (slot-value object 'keycodes) (- keycode (slot-value object 'min-keycode))) group-info (slot-value keycode 'groupInfo) group-number (logand group-info 15)) (if (= group-number 0) (progn (throw 'return '(0 . 0)))) (setq group (if (null modifiers) 0 (logand (lsh modifiers -13) 3))) (if (>= group group-number) (progn (let* ((val (logand group-info 192))) (cond ((eq val 'xcb:xkb:GroupsWrap:RedirectIntoRange) (setq group (logand 255 ...)) (if (>= group group-number) (progn ...))) ((eq val 'xcb:xkb:GroupsWrap:ClampIntoRange) (setq group (1- group-number))) (t (setq group (% group group-number))))))) (setq index (* group (slot-value keycode 'width))) (progn (message "KEYSTROKE keysym: %s kt-index: %s" (slot-value keycode 'syms) (slot-value keycode 'kt-index)) (let* ((object keycode)) (message "KEYSTROKE keysym: %s kt-index: %s" (slot-value object 'syms) (slot-value object 'kt-index))) (message "number of keysyms: %s" (length (slot-value object 'keycodes))) (message "number of keytypes: %s" (length (slot-value object 'keytypes))) (let* ((--cl-vec-- (slot-value object 'keycodes)) (--cl-idx-- -1) (code nil)) (while (< (setq --cl-idx-- (1+ --cl-idx--)) (length --cl-vec--)) (setq code (aref --cl-vec-- --cl-idx--)) (if code (progn (let* (...) (if ... ...))))) nil)) (setq keytype (aref (slot-value object 'keytypes) (elt (slot-value keycode 'kt-index) group))) (let* ((object keytype)) (if (null modifiers) (delq nil (mapcar #'(lambda (entry) (if ... ...)) (slot-value object 'map))) (catch 'break (let ((--dolist-tail-- (slot-value object ...))) (while --dolist-tail-- (let (...) (let* ... ...) (setq --dolist-tail-- ...))))) (cons (elt (slot-value keycode 'syms) index) (logand (slot-value object 'mods-mask) (lognot preserve)))))) (let* ((object (xcb:keysyms:-get-current-device obj))) (catch 'return (if (<= (slot-value object 'min-keycode) keycode (slot-value object 'max-keycode)) nil (throw 'return '(0 . 0))) (setq keycode (aref (slot-value object 'keycodes) (- keycode (slot-value object 'min-keycode))) group-info (slot-value keycode 'groupInfo) group-number (logand group-info 15)) (if (= group-number 0) (progn (throw 'return '(0 . 0)))) (setq group (if (null modifiers) 0 (logand (lsh modifiers -13) 3))) (if (>= group group-number) (progn (let* ((val (logand group-info 192))) (cond ((eq val ...) (setq group ...) (if ... ...)) ((eq val ...) (setq group ...)) (t (setq group ...)))))) (setq index (* group (slot-value keycode 'width))) (progn (message "KEYSTROKE keysym: %s kt-index: %s" (slot-value keycode 'syms) (slot-value keycode 'kt-index)) (let* ((object keycode)) (message "KEYSTROKE keysym: %s kt-index: %s" (slot-value object 'syms) (slot-value object 'kt-index))) (message "number of keysyms: %s" (length (slot-value object 'keycodes))) (message "number of keytypes: %s" (length (slot-value object 'keytypes))) (let* ((--cl-vec-- (slot-value object 'keycodes)) (--cl-idx-- -1) (code nil)) (while (< (setq --cl-idx-- (1+ --cl-idx--)) (length --cl-vec--)) (setq code (aref --cl-vec-- --cl-idx--)) (if code (progn (let* ... ...)))) nil)) (setq keytype (aref (slot-value object 'keytypes) (elt (slot-value keycode 'kt-index) group))) (let* ((object keytype)) (if (null modifiers) (delq nil (mapcar #'(lambda ... ...) (slot-value object 'map))) (catch 'break (let ((--dolist-tail-- ...)) (while --dolist-tail-- (let ... ... ...)))) (cons (elt (slot-value keycode 'syms) index) (logand (slot-value object 'mods-mask) (lognot preserve))))))) (let ((preserve 0) group group-info group-number index keytype) (let* ((object (xcb:keysyms:-get-current-device obj))) (catch 'return (if (<= (slot-value object 'min-keycode) keycode (slot-value object 'max-keycode)) nil (throw 'return '(0 . 0))) (setq keycode (aref (slot-value object 'keycodes) (- keycode (slot-value object 'min-keycode))) group-info (slot-value keycode 'groupInfo) group-number (logand group-info 15)) (if (= group-number 0) (progn (throw 'return '(0 . 0)))) (setq group (if (null modifiers) 0 (logand (lsh modifiers -13) 3))) (if (>= group group-number) (progn (let* ((val ...)) (cond (... ... ...) (... ...) (t ...))))) (setq index (* group (slot-value keycode 'width))) (progn (message "KEYSTROKE keysym: %s kt-index: %s" (slot-value keycode 'syms) (slot-value keycode 'kt-index)) (let* ((object keycode)) (message "KEYSTROKE keysym: %s kt-index: %s" (slot-value object 'syms) (slot-value object 'kt-index))) (message "number of keysyms: %s" (length (slot-value object 'keycodes))) (message "number of keytypes: %s" (length (slot-value object 'keytypes))) (let* ((--cl-vec-- (slot-value object ...)) (--cl-idx-- -1) (code nil)) (while (< (setq --cl-idx-- ...) (length --cl-vec--)) (setq code (aref --cl-vec-- --cl-idx--)) (if code (progn ...))) nil)) (setq keytype (aref (slot-value object 'keytypes) (elt (slot-value keycode 'kt-index) group))) (let* ((object keytype)) (if (null modifiers) (delq nil (mapcar #'... (slot-value object ...))) (catch 'break (let (...) (while --dolist-tail-- ...))) (cons (elt (slot-value keycode ...) index) (logand (slot-value object ...) (lognot preserve)))))))) (progn (let ((preserve 0) group group-info group-number index keytype) (let* ((object (xcb:keysyms:-get-current-device obj))) (catch 'return (if (<= (slot-value object 'min-keycode) keycode (slot-value object 'max-keycode)) nil (throw 'return '(0 . 0))) (setq keycode (aref (slot-value object 'keycodes) (- keycode (slot-value object ...))) group-info (slot-value keycode 'groupInfo) group-number (logand group-info 15)) (if (= group-number 0) (progn (throw 'return '...))) (setq group (if (null modifiers) 0 (logand (lsh modifiers -13) 3))) (if (>= group group-number) (progn (let* (...) (cond ... ... ...)))) (setq index (* group (slot-value keycode 'width))) (progn (message "KEYSTROKE keysym: %s kt-index: %s" (slot-value keycode 'syms) (slot-value keycode 'kt-index)) (let* ((object keycode)) (message "KEYSTROKE keysym: %s kt-index: %s" (slot-value object ...) (slot-value object ...))) (message "number of keysyms: %s" (length (slot-value object ...))) (message "number of keytypes: %s" (length (slot-value object ...))) (let* ((--cl-vec-- ...) (--cl-idx-- -1) (code nil)) (while (< ... ...) (setq code ...) (if code ...)) nil)) (setq keytype (aref (slot-value object 'keytypes) (elt (slot-value keycode ...) group))) (let* ((object keytype)) (if (null modifiers) (delq nil (mapcar ... ...)) (catch 'break (let ... ...)) (cons (elt ... index) (logand ... ...)))))))) (closure (t) (obj keycode modifiers) "Convert KEYCODE to keysym or get possible modifier..." (progn (let ((preserve 0) group group-info group-number index keytype) (let* ((object (xcb:keysyms:-get-current-device obj))) (catch 'return (if (<= ... keycode ...) nil (throw ... ...)) (setq keycode (aref ... ...) group-info (slot-value keycode ...) group-number (logand group-info 15)) (if (= group-number 0) (progn ...)) (setq group (if ... 0 ...)) (if (>= group group-number) (progn ...)) (setq index (* group ...)) (progn (message "KEYSTROKE keysym: %s kt-index: %s" ... ...) (let* ... ...) (message "number of keysyms: %s" ...) (message "number of keytypes: %s" ...) (let* ... ... nil)) (setq keytype (aref ... ...)) (let* (...) (if ... ... ... ...)))))))(#<xcb:connection xcb:connection-ca0fd0> 20 16) apply((closure (t) (obj keycode modifiers) "Convert KEYCODE to keysym or get possible modifier..." (progn (let ((preserve 0) group group-info group-number index keytype) (let* ((object (xcb:keysyms:-get-current-device obj))) (catch 'return (if (<= ... keycode ...) nil (throw ... ...)) (setq keycode (aref ... ...) group-info (slot-value keycode ...) group-number (logand group-info 15)) (if (= group-number 0) (progn ...)) (setq group (if ... 0 ...)) (if (>= group group-number) (progn ...)) (setq index (* group ...)) (progn (message "KEYSTROKE keysym: %s kt-index: %s" ... ...) (let* ... ...) (message "number of keysyms: %s" ...) (message "number of keytypes: %s" ...) (let* ... ... nil)) (setq keytype (aref ... ...)) (let* (...) (if ... ... ... ...))))))) #<xcb:connection xcb:connection-ca0fd0> (20 16)) xcb:keysyms:keycode->keysym(#<xcb:connection xcb:connection-ca0fd0> 20 16)
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.