GNU bug report logs - #68914
Windows makes Emacs choke on and swallow the WIN keys

Previous Next

Package: emacs;

Reported by: Raffael Stocker <r.stocker <at> mnet-mail.de>

Date: Sat, 3 Feb 2024 22:23:02 UTC

Severity: normal

To reply to this bug, email your comments to 68914 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#68914; Package emacs. (Sat, 03 Feb 2024 22:23:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Raffael Stocker <r.stocker <at> mnet-mail.de>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Sat, 03 Feb 2024 22:23:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Raffael Stocker <r.stocker <at> mnet-mail.de>
To: bug-gnu-emacs <at> gnu.org
Subject: Windows makes Emacs choke on and swallow the WIN keys
Date: Sat, 03 Feb 2024 21:45:46 +0100
Hi,

this is a weird one (and long, apologies).  On MS Windows, it sometimes
happens that a windows key gets stuck, that is, it remains (logically)
pressed down, and this behaviour is correlated with Emacs use.  A
colleague and I are seeing this on two installations with Emacs 28.2 and
29.2 on Windows 10 and 11.  Unfortunately, this is somewhat random and
we have not found a way to trigger it directly.

Emacs implements WIN key handling using the low level keyboard API in
the ‘funhook’ callback function in ‘src/w32fnc.c’.  Microsoft write
about this hook that the application must handle the hook within some
timeout.  If it doesn't, the hook is silently removed [0]:

MS> The hook procedure should process a message in less time than the data
MS> entry specified in the LowLevelHooksTimeout value in the following
MS> registry key:
MS> 
MS> HKEY_CURRENT_USER**\**Control Panel**\**Desktop
MS> 
MS> The value is in milliseconds. If the hook procedure times out, the
MS> system passes the message to the next hook. However, on Windows 7
MS> and later, the hook is silently removed without being called. There
MS> is no way for the application to know whether the hook is removed.
MS> 
MS> Windows 10 version 1709 and later The maximum timeout value the
MS> system allows is 1000 milliseconds (1 second). The system will
MS> default to using a 1000 millisecond timeout if the
MS> LowLevelHooksTimeout value is set to a value larger than 1000.

It seems that this might be what happens to Emacs.  Possibly Windows
removes the keyboard hook due to a timeout, not giving Emacs a chance to
produce a ‘WM_KEYUP’ event.  And it seems to be correlated with working
on Windows network shares; we also have Windows Defender active, which
might make matters worse by slowing Emacs down while it is writing to a
file.

We have had good results with increasing the ‘LowLevelHooksTimeout’, but
we had to set it to the maximum value of 1000 ms.  I am not sure about
the default value; the internet claims it to be 200 ms.  A mid-range
value (500 ms) alleviated the problem somewhat, but it seems to require
the maximum to vanish, at least judging by a limited experience of a few
days of observation.

I am not sure there is an Emacs bug at all here, but I think it warrants
some investigation:

- Might it be possible to find a way to trigger this behaviour using a
  debugger?  Unfortunately, I can neither compile nor debug on the
  Windows machines (company computers with limited usefulness...).
- If Emacs being too slow somewhere is indeed the problem, can it be
  sped up, maybe by putting the slow stuff in a different thread than
  the low level keyboard handling?
- Can we put the workaround described above (with the LowLevelHooksTimeout
  value) into the Emacs documentation so it is findable?

In related news, I noticed that the input events constructed in
‘funhook’ seem to use incorrect scan codes, for example starting at line
2630 in w32fns.c:

--8<---------------cut here---------------start------------->8---
inputs[0].type = INPUT_KEYBOARD;
inputs[0].ki.wVk = hs->vkCode;
inputs[0].ki.wScan = hs->vkCode;
inputs[0].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
inputs[0].ki.time = 0;
inputs[1].type = INPUT_KEYBOARD;
inputs[1].ki.wVk = hs->vkCode;
inputs[1].ki.wScan = hs->vkCode;
inputs[1].ki.dwFlags
= KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
inputs[1].ki.time = 0;
--8<---------------cut here---------------end--------------->8---

This sets both ki.wVk and ki.wScan to the virtual-key code (0x5B for
VK_LWIN), but the ‘KEYEVENTF_EXTENDEDKEY’ flag is set, which IIUC would
require adding ‘0xE0’ to the virtual-key code to obtain the scan code,
e.g. 0xE05B for LWIN [1].  Can this cause any (additional) problems?

And, BTW, why is the callback called ‘funhook’?  Using the Windows low
level keyboard API doesn't seem to be much fun and I can't see anyone
get hooked on this either.

Regards,
Raffael

[0] https://learn.microsoft.com/en-us/windows/win32/winmsg/lowlevelkeyboardproc
[1] https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-keybdinput




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68914; Package emacs. (Sun, 04 Feb 2024 06:32:02 GMT) Full text and rfc822 format available.

Message #8 received at 68914 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Raffael Stocker <r.stocker <at> mnet-mail.de>
Cc: 68914 <at> debbugs.gnu.org
Subject: Re: bug#68914: Windows makes Emacs choke on and swallow the WIN keys
Date: Sun, 04 Feb 2024 08:31:15 +0200
> From: Raffael Stocker <r.stocker <at> mnet-mail.de>
> Date: Sat, 03 Feb 2024 21:45:46 +0100
> 
> It seems that this might be what happens to Emacs.  Possibly Windows
> removes the keyboard hook due to a timeout, not giving Emacs a chance to
> produce a ‘WM_KEYUP’ event.  And it seems to be correlated with working
> on Windows network shares; we also have Windows Defender active, which
> might make matters worse by slowing Emacs down while it is writing to a
> file.
> 
> We have had good results with increasing the ‘LowLevelHooksTimeout’, but
> we had to set it to the maximum value of 1000 ms.  I am not sure about
> the default value; the internet claims it to be 200 ms.  A mid-range
> value (500 ms) alleviated the problem somewhat, but it seems to require
> the maximum to vanish, at least judging by a limited experience of a few
> days of observation.

It would be better to have some independent verification that this is
what happens.  Is there any way to find out whether the hook was
removed, even from outside of Emacs?  I find it hard to believe that
we could miss the 200-ms deadline on modern systems.  Are your systems
heavily loaded at times?  What kind of CPU do you have on those
systems?  Emacs can hog CPU with only a single thread, so if your
systems have a reasonably modern CPU, Windows should have plenty of
execution units to spread any additional load without preempting
Emacs.

Another idea is to add code to Emacs that measures the time it takes
Emacs to produce the WM_KEYUP event, and log some message if that
takes more than some threshold.

> - Might it be possible to find a way to trigger this behaviour using a
>   debugger?  Unfortunately, I can neither compile nor debug on the
>   Windows machines (company computers with limited usefulness...).

That's probably tricky, given the time constraints.

> - If Emacs being too slow somewhere is indeed the problem, can it be
>   sped up, maybe by putting the slow stuff in a different thread than
>   the low level keyboard handling?

According to the MS documentation, the hook is called by sending a
message to the thread that installed the hook, which in our case is
already a separate thread, not the main Lisp thread (which is likely
to be busy at times).  The thread which handles the hook callbacks is
the input thread, which is relatively light-weight and shouldn't be
too busy.

> - Can we put the workaround described above (with the LowLevelHooksTimeout
>   value) into the Emacs documentation so it is findable?

Please suggest the text to put in the manual to document this.

> In related news, I noticed that the input events constructed in
> ‘funhook’ seem to use incorrect scan codes, for example starting at line
> 2630 in w32fns.c:
> 
> --8<---------------cut here---------------start------------->8---
> inputs[0].type = INPUT_KEYBOARD;
> inputs[0].ki.wVk = hs->vkCode;
> inputs[0].ki.wScan = hs->vkCode;
> inputs[0].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
> inputs[0].ki.time = 0;
> inputs[1].type = INPUT_KEYBOARD;
> inputs[1].ki.wVk = hs->vkCode;
> inputs[1].ki.wScan = hs->vkCode;
> inputs[1].ki.dwFlags
> = KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP;
> inputs[1].ki.time = 0;
> --8<---------------cut here---------------end--------------->8---
> 
> This sets both ki.wVk and ki.wScan to the virtual-key code (0x5B for
> VK_LWIN), but the ‘KEYEVENTF_EXTENDEDKEY’ flag is set, which IIUC would
> require adding ‘0xE0’ to the virtual-key code to obtain the scan code,
> e.g. 0xE05B for LWIN [1].  Can this cause any (additional) problems?

I'm not an expert, but this code was working for years.  However, you
could try making the change you propose and see if that solves the
problem (or causes new ones).

> And, BTW, why is the callback called ‘funhook’?  Using the Windows low
> level keyboard API doesn't seem to be much fun and I can't see anyone
> get hooked on this either.

I think this question is for the author of the code.  I'm not sure he
is reading this.  There's nothing wrong with the name from my POV.

Thanks.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68914; Package emacs. (Sun, 04 Feb 2024 13:16:01 GMT) Full text and rfc822 format available.

Message #11 received at 68914 <at> debbugs.gnu.org (full text, mbox):

From: Raffael Stocker <r.stocker <at> mnet-mail.de>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 68914 <at> debbugs.gnu.org
Subject: Re: bug#68914: Windows makes Emacs choke on and swallow the WIN keys
Date: Sun, 04 Feb 2024 14:02:02 +0100
[Message part 1 (text/plain, inline)]
Eli Zaretskii <eliz <at> gnu.org> writes:

> It would be better to have some independent verification that this is
> what happens.  Is there any way to find out whether the hook was
> removed, even from outside of Emacs?

MS say there is no direct way.  But for debugging it might be possible
to produce some output whenever the hook is called, if that is missing,
we would know.

> I find it hard to believe that
> we could miss the 200-ms deadline on modern systems.  Are your systems
> heavily loaded at times?  What kind of CPU do you have on those
> systems?  Emacs can hog CPU with only a single thread, so if your
> systems have a reasonably modern CPU, Windows should have plenty of
> execution units to spread any additional load without preempting
> Emacs.

It (also) happens when the systems are basically idle, with only some
keyboard input.  The systems are also relatively new (Intel i7 or i5
from a few years ago).

> Another idea is to add code to Emacs that measures the time it takes
> Emacs to produce the WM_KEYUP event, and log some message if that
> takes more than some threshold.

I have managed to set up a build environment on one of the machines and
I will try to experiment with this in the coming weeks. Perhaps I can
find out more.

>> - If Emacs being too slow somewhere is indeed the problem, can it be
>>   sped up, maybe by putting the slow stuff in a different thread than
>>   the low level keyboard handling?
>
> According to the MS documentation, the hook is called by sending a
> message to the thread that installed the hook, which in our case is
> already a separate thread, not the main Lisp thread (which is likely
> to be busy at times).  The thread which handles the hook callbacks is
> the input thread, which is relatively light-weight and shouldn't be
> too busy.

We saw the correlation with working on a network share and IIUC Windows
Defender blocks a process/thread while writing (or only closing?) a
file.  Therefore my suspicion.  But if saving files is not done in the
same thread as input, that can't be it...

>> - Can we put the workaround described above (with the LowLevelHooksTimeout
>>   value) into the Emacs documentation so it is findable?
>
> Please suggest the text to put in the manual to document this.

I attached a patch that adds a paragraph to the “Windows Keyboard” section.

>> This sets both ki.wVk and ki.wScan to the virtual-key code (0x5B for
>> VK_LWIN), but the ‘KEYEVENTF_EXTENDEDKEY’ flag is set, which IIUC would
>> require adding ‘0xE0’ to the virtual-key code to obtain the scan code,
>> e.g. 0xE05B for LWIN [1].  Can this cause any (additional) problems?
>
> I'm not an expert, but this code was working for years.  However, you
> could try making the change you propose and see if that solves the
> problem (or causes new ones).

I'll give it a try.

Regards,
Raffael

[0001-Document-workaround-for-a-stuck-Windows-key-on-MS-Wi.patch (text/x-patch, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68914; Package emacs. (Sun, 04 Feb 2024 13:34:02 GMT) Full text and rfc822 format available.

Message #14 received at 68914 <at> debbugs.gnu.org (full text, mbox):

From: Nikolay Kudryavtsev <nikolay.kudryavtsev <at> gmail.com>
To: Raffael Stocker <r.stocker <at> mnet-mail.de>, 68914 <at> debbugs.gnu.org
Subject: Re: bug#68914: Windows makes Emacs choke on and swallow the WIN keys
Date: Sun, 4 Feb 2024 16:32:48 +0300
Hello.

I think I've seen this bug in the wild a couple of times too.

But there's something else. I'm not sure if it's the same bug, but 
something's been iffy about Emacs keyboard input handling on Windows for 
the last few major versions.

Unfortunately I've yet to find a simple reproduction recipe and hence 
why I haven't filled that one the tracker. The problem is as follows.

I use a certain piece of software that switches between keyboard layouts 
by CAPS LOCK. So CAPS LOCK, the feature, is normally mostly inactive on 
my machine and requires a certain other combination to activate. Emacs 
normally respects that. Except when it's under a load running lisp code. 
During that time there are time intervals during which pressing CAPS 
LOCK would incorrectly set it on for me.

One way I can reliably reproduce this is by doing M-x list-packages and 
then tapping CAPS LOCK. At some point it would light up.

Thus I believe that the input handling intermittently breaks during the 
high load(lisp evaluation).

My testing had shown that the last version that does not suffer from 
this is Emacs 25.

Just posting this in case it's the same problem and this information is 
of any use in debugging.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68914; Package emacs. (Sun, 04 Feb 2024 13:57:03 GMT) Full text and rfc822 format available.

Message #17 received at 68914 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Nikolay Kudryavtsev <nikolay.kudryavtsev <at> gmail.com>
Cc: r.stocker <at> mnet-mail.de, 68914 <at> debbugs.gnu.org
Subject: Re: bug#68914: Windows makes Emacs choke on and swallow the WIN keys
Date: Sun, 04 Feb 2024 15:56:31 +0200
> From: Nikolay Kudryavtsev <nikolay.kudryavtsev <at> gmail.com>
> Date: Sun, 4 Feb 2024 16:32:48 +0300
> 
> But there's something else. I'm not sure if it's the same bug, but 
> something's been iffy about Emacs keyboard input handling on Windows for 
> the last few major versions.

I don't think it's the same issue.  I suggest submitting a separate
bug report with the details.

> Unfortunately I've yet to find a simple reproduction recipe and hence 
> why I haven't filled that one the tracker. The problem is as follows.
> 
> I use a certain piece of software that switches between keyboard layouts 
> by CAPS LOCK. So CAPS LOCK, the feature, is normally mostly inactive on 
> my machine and requires a certain other combination to activate. Emacs 
> normally respects that. Except when it's under a load running lisp code. 
> During that time there are time intervals during which pressing CAPS 
> LOCK would incorrectly set it on for me.
> 
> One way I can reliably reproduce this is by doing M-x list-packages and 
> then tapping CAPS LOCK. At some point it would light up.

In the bug report I suggest to submit, please describe in more detail
how to reproduce this using list-packages.  How to "tap CAPS LOCK" and
what to look for while doing that.  I just tried naïvely to reproduce
that and didn't see any problems, probably because I didn't know where
to look.

> Thus I believe that the input handling intermittently breaks during the 
> high load(lisp evaluation).
> 
> My testing had shown that the last version that does not suffer from 
> this is Emacs 25.

Emacs 26 introduced the low-level keyboard hook.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68914; Package emacs. (Sun, 04 Feb 2024 14:16:01 GMT) Full text and rfc822 format available.

Message #20 received at 68914 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Raffael Stocker <r.stocker <at> mnet-mail.de>
Cc: 68914 <at> debbugs.gnu.org
Subject: Re: bug#68914: Windows makes Emacs choke on and swallow the WIN keys
Date: Sun, 04 Feb 2024 16:14:57 +0200
> From: Raffael Stocker <r.stocker <at> mnet-mail.de>
> Cc: 68914 <at> debbugs.gnu.org
> Date: Sun, 04 Feb 2024 14:02:02 +0100
> 
> > It would be better to have some independent verification that this is
> > what happens.  Is there any way to find out whether the hook was
> > removed, even from outside of Emacs?
> 
> MS say there is no direct way.  But for debugging it might be possible
> to produce some output whenever the hook is called, if that is missing,
> we would know.

That could be a good solution, yes.

> > I find it hard to believe that
> > we could miss the 200-ms deadline on modern systems.  Are your systems
> > heavily loaded at times?  What kind of CPU do you have on those
> > systems?  Emacs can hog CPU with only a single thread, so if your
> > systems have a reasonably modern CPU, Windows should have plenty of
> > execution units to spread any additional load without preempting
> > Emacs.
> 
> It (also) happens when the systems are basically idle, with only some
> keyboard input.  The systems are also relatively new (Intel i7 or i5
> from a few years ago).

That's even weirder.

> > Another idea is to add code to Emacs that measures the time it takes
> > Emacs to produce the WM_KEYUP event, and log some message if that
> > takes more than some threshold.
> 
> I have managed to set up a build environment on one of the machines and
> I will try to experiment with this in the coming weeks. Perhaps I can
> find out more.

Thanks.

> >> - If Emacs being too slow somewhere is indeed the problem, can it be
> >>   sped up, maybe by putting the slow stuff in a different thread than
> >>   the low level keyboard handling?
> >
> > According to the MS documentation, the hook is called by sending a
> > message to the thread that installed the hook, which in our case is
> > already a separate thread, not the main Lisp thread (which is likely
> > to be busy at times).  The thread which handles the hook callbacks is
> > the input thread, which is relatively light-weight and shouldn't be
> > too busy.
> 
> We saw the correlation with working on a network share and IIUC Windows
> Defender blocks a process/thread while writing (or only closing?) a
> file.  Therefore my suspicion.  But if saving files is not done in the
> same thread as input, that can't be it...

Our input thread doesn't write to any files, not in our code anyway.
It just runs the message pump and little else.

> >> - Can we put the workaround described above (with the LowLevelHooksTimeout
> >>   value) into the Emacs documentation so it is findable?
> >
> > Please suggest the text to put in the manual to document this.
> 
> I attached a patch that adds a paragraph to the “Windows Keyboard” section.

On second thought, I think this kind of problems are better described
in etc/PROBLEMS, so I have now added something there with the
description of the problem and the workaround/




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#68914; Package emacs. (Mon, 12 Feb 2024 20:56:01 GMT) Full text and rfc822 format available.

Message #23 received at 68914 <at> debbugs.gnu.org (full text, mbox):

From: Raffael Stocker <r.stocker <at> mnet-mail.de>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 68914 <at> debbugs.gnu.org
Subject: Re: bug#68914: Windows makes Emacs choke on and swallow the WIN keys
Date: Mon, 12 Feb 2024 21:13:27 +0100
[Message part 1 (text/plain, inline)]
I have added debug output to the keyboard hook (see the attached patch)
and was able to observe the bug while Emacs was unresponsive (either
because the current master is iffy on Windows or because of my
output...).  The locked windows key problem seems to appear when an
s-<something> combination is pressed.  Normal debug output looks like
this:

--8<---------------cut here---------------start------------->8---
KEYDOWN 0x5b, 0x5b: 0.0018 ms

Simulated S-x combination: 0.647 ms

KEYUP received, winsdown: 1, w: 0x101
no key pressed anymore, clear flags
KEYUP processed normally: 4.57 ms
--8<---------------cut here---------------end--------------->8---

Emacs first registers the windows key to be pressed in a WM_KEYDOWN
event, then upon the second call of ‘funhook’ sees the other key in the
combination and sends a WIN+<x> input to the system and then in the
third call receives the WM_KEYUP event, cleans up its state and calls
‘CallNextHookEx’ to let other applications in the hook chain process the
combination normally.  The times are the execution times of the hook.

With the bug present, I get the following output:

--8<---------------cut here---------------start------------->8---
KEYDOWN 0x5b, 0x5b: 0.0005 ms

Simulated S-x combination: 1.08 ms

0 < winsdown = 1: 0.0015 ms

0 < winsdown = 1: 0.0015 ms

0 < winsdown = 1: 0.0016 ms
--8<---------------cut here---------------end--------------->8---

The WM_KEYUP event is missing here; instead, if I press any key, Emacs
ignores it and calls ‘CallNextHookEx’ normally; the above output shows
three such key presses.  If I press ‘e’ now, Windows Explorer will
open.  That is, Emacs doesn't seem to receive the WM_KEYUP event, but
the system doesn't seem to see it either (unless my understanding of the
situation is completely wrong).

Note that the times shown above are very short; I have seen up to 15 ms,
but nothing longer.  Emacs was unresponsive for a few seconds while the
behaviour occurred; but if the hook was removed by Windows, this was not
permanent, as the remaining output shows.  Also, pressing a windows key
seems to cure the problem in this case.

I will continue to observe this and try to find out more, but any
insights are welcome.

Regards,
Raffael

[funhook-debug-prints.patch (text/x-patch, attachment)]

This bug report was last modified 81 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.