A high A_MaxHotkeysPerInterval can freeze your system!

Discuss Autohotkey related topics here. Not a place to share code.
Forum rules
Discuss Autohotkey related topics here. Not a place to share code.
Rok
Posts: 63
Joined: 11 Jan 2016, 08:50

A high A_MaxHotkeysPerInterval can freeze your system!

Post by Rok » 10 Jun 2023, 13:49

This issue may be quite obvious to veterans, but I'm somewhere from beginner to intermediate in AutoHotkey. And years ago, the A_MaxHotkeysPerInterval := 10000 line was recommended to me for some problem with an AHK script in a game. I believe that the problem was indeed solved by that setting back then, so I've kept the line since then.

However, for other beginners like me, be warned: Such a high setting for the A_MaxHotkeysPerInterval command can freeze your whole system for at least several seconds with certain hotkeys!

That's enough to know for people who come across this and want a quick answer to their problem. But if someone wants to understand how I discovered this, which may help people who answer beginners' questions if my circumstances match the details that someone else posts on the forums, for example, then please read on.

It is safe to assume that I may not be the only one who sort of "inherited" this line at the top of my main AHK script, and it has always been there without me understanding in the beginning what it really does. And even if I understood, the line has been added years ago, and I pretty much forgot about it.

In the last few days, my whole computer would sometimes freeze for more than a minute and become unresponsive or extremely slow to respond. And for the life of me, I couldn't figure out what it was. I reinstalled an antivirus, tracked the PC performance in Task Manager, and saw nothing out of the ordinary or suspicious. It wasn't until the last few minutes that it suddenly dawned on me instinctively that the computer behaved that way — froze like that — when I pressed specific keys: Shift+2. And I remembered that that shortcut has been in my main AHK script for years. So, I made the connection and did some research. I tested the simplest script and saw the error message, "71 hotkeys have been received in the last 31ms," with the super helpful addition, "(see A_MaxHotkeysPerInterval in the help file)." Mind you, this error message did not show up when I had the script with A_MaxHotkeysPerInterval := 10000 running!

At that point, it was easy for me to remember that line at the top of my main script, and I understood what was happening.

This wasn't a problem with AHK v1, maybe because I had the code as:

Code: Select all

+2::
send {@}
return
Maybe the braces made the difference, or maybe something else was happening with my machine that allowed the hotkey to run smoothly with the high setting for A_MaxHotkeysPerInterval. All I know is that I did not upgrade my computer at all from the point when my computer was running smoothly with the old script to when the freezing problem started to happen.

After my fairly recent upgrade from AHK v1 to v2, however, I changed the hotkey code to:

Code: Select all

+2:: {
  Send "@"
}
Perhaps this is related to why Shift+2 kept freezing my computer for almost a minute sometimes in the last few days.

However, my computer and script worked just fine after removing the A_MaxHotkeysPerInterval line altogether just to be safe and changing the hotkey code to:

Code: Select all

$+2:: {
  Send "@"
}
Also, for whatever reason, the above format wasn't working at all with Shift+3, so I added braces to both hotkeys like so and it worked:

Code: Select all

$+3:: {
  Send "{#}"
}
If someone is wondering why I'm using AHK hotkeys to simulate behavior that already exists by default on some Windows input methods or keyboards, which is directly related to why this loop occurs, hence the system freezing, then it's because I like my script to be "portable" or usable on others' machines sometimes without having to change the input method or language in the operating system.

I hope this can help others somehow. I can't post in Tutorials, not asking for help here, and my post is more of a warning to beginners rather than a "working script," so I didn't know where else to post this on the forums.

lexikos
Posts: 9592
Joined: 30 Sep 2013, 04:07
Contact:

Re: A high A_MaxHotkeysPerInterval can freeze your system!

Post by lexikos » 07 Jul 2023, 21:45

The documentation already warns about this:
Care should be taken not to make the above too lenient because if you ever inadvertently introduce an infinite loop of keystrokes (via a Send function that accidentally triggers other hotkeys), your computer could become unresponsive due to the rapid flood of keyboard events.
Source: A_MaxHotkeysPerInterval - Syntax & Usage | AutoHotkey v2

The system is likely not "freezing" or even slowing down. Sending keys in a tight loop makes the keyboard very difficult to use - that is probably what you were observing. Another way to similarly "freeze your system" would be to unplug your keyboard. ;)

For "@", the braces make no difference to anything. Braces are necessary for "#" because by default it is interpreted as a modifier (Win). In current versions it is ignored if not followed by something else (but that's only true for Send, not hotkeys).

The default behaviour of Send in v2 is not identical to v1, but the differences aren't relevant to this case. The issue is that you have registered a hotkey for Shift+2, and then you are sending Shift+2. By default, the hotkey will trigger itself in a tight loop. This happens on both versions. The solution is generally to use the $ prefix.
$

This is usually only necessary if the script uses the Send function to send the keys that comprise the hotkey itself, which might otherwise cause it to trigger itself. The $ prefix forces the keyboard hook to be used to implement this hotkey, which as a side-effect prevents the Send function from triggering it. The $ prefix is equivalent to having specified #UseHook somewhere above the definition of this hotkey.

The $ prefix [...] has no effect for hotkeys which already require the keyboard hook, [...]. To determine whether a particular hotkey uses the keyboard hook, use ListHotkeys.
Source: Hotkeys - Definition & Usage | AutoHotkey v2
Perhaps something changed in your environment when you upgraded, and +2:: could not be registered and was instead implemented using the keyboard hook.
This wasn't a problem with AHK v1
Perhaps you didn't have that problem, but the code you had is unlikely to work on v1. On my system, the hotkey blocks the keystrokes sent by Send {@}, but due to some subtle difference in threading or message-checking behaviour, the hotkey is still considered to be running when the hotkey message arrives and so the default setting of #MaxThreadsPerHotkey prevents the hotkey from looping. If I use #MaxThreadsPerHotkey 10, the hotkey executes 10 threads and then ignores the last sent key combination. Either way, it has no visible effect unless something else is added to the hotkey (i.e. the hotkey does not work).

Code: Select all

; #MaxThreadsPerHotkey 10
n:=0
+2::
	send @  ; It behaves the same with braces.
	ToolTip % ++n
	return
In this case, the tooltip shows 1 unless the top line is uncommented, in which case it shows 10 and the Shift key usually gets stuck down until I physically press it.

On v2, the hotkey returns before the next hotkey message is processed, so #MaxThreadsPerHotkey does not apply, and only A_MaxHotkeysPerInterval may stop the loop.
However, my computer and script worked just fine after removing the A_MaxHotkeysPerInterval line altogether
It has nothing to do with reducing A_MaxHotkeysPerInterval. That would only have the effect of showing a warning message when the limit is reached. The hotkey still wouldn't work.
and changing the hotkey code to [include $]
That's the important point.

Another way to avoid the issue is to use SendText or Text mode. SendText "#" does not trigger hotkeys (or keyboard shortcuts in applications), because it sends text as text, not by translating it to a key combination. Braces are interpreted literally, so should not be used.

Post Reply

Return to “General Discussion”