Confirmed bug with #if and Hotkey, If Topic is solved

Report problems with documented functionality
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Confirmed bug with #if and Hotkey, If

01 May 2020, 17:03

Introduction
Hello, when using #if or Hotkey, If in combination with a function that sends a key, you get weird stuff being sent.

Code: Select all

#NoEnv
#installkeybdhook
#installmousehook
#MaxHotkeysPerInterval 99000000
#HotkeyInterval 99000000
#MaxThreadsPerHotkey 2
#KeyHistory 0
ListLines Off
SetBatchLines, -1
SetKeyDelay, -1, -1
SetMouseDelay, -1
SetDefaultMouseSpeed, 0
SetWinDelay, -1
SetControlDelay, -1
SendMode Input

fn := Func("notepadActive")
Hotkey, If, % fn
Hotkey, % "$w", % "testbug", % "on"
return

testbug:
while(GetKeyState("w", "p"))
{
	sendKey_f("a")
	sleep, 10
}
return

sendKey_f(key)
{
	global
	sendEvent % "{" key "}"
}

notepadActive()
{
	return WinActive("ahk_exe notepad++.exe")
}
Steps to reproduce the bug
1. Hold down w

What happens?:
Image
In case it is too small, here is the video: https://i.gyazo.com/ae99696f89f0cc762d24822723b8d47c.mp4
In case that's not enough: Weird stuff is being sent in between the "a"s

I don't know why this happens, but it won't happen if you:
1. Replace the function call with sendEvent
2. Replace the sendEvent inside the function with sendInput (but this gives other issues)

I couldn't test it in ahk_l
User avatar
Delta Pythagorean
Posts: 627
Joined: 13 Feb 2017, 13:44
Location: Somewhere in the US
Contact:

Re: Confirmed bug with #if and Hotkey, If

01 May 2020, 19:51

I have a few questions:
  1. Why are you forcing Global inside of a function that doesn't need global?
  2. Is there a particular reason why are you using SendEvent versus something else?
  3. Why do you have a function dedicated to returning whether notepad++ is active? Why not just put the WinActive call on the same line?
  4. What build of AHK are you using? Are you using Unicode or ANSI?
  5. Since you said you couldn't test it in AHK_L are you using AHK_H?

[AHK]......: v2.0.12 | 64-bit
[OS].......: Windows 11 | 23H2 (OS Build: 22621.3296)
[GITHUB]...: github.com/DelPyth
[PAYPAL]...: paypal.me/DelPyth
[DISCORD]..: tophatcat

HotKeyIt
Posts: 2364
Joined: 29 Sep 2013, 18:35
Contact:

Re: Confirmed bug with #if and Hotkey, If

01 May 2020, 20:16

kyuuuri posted originally in AHK_H, but I tested it on AHK_L 1.1.32.00 and it produces the same as AHK_H, so I moved it to Bug Reports!
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: Confirmed bug with #if and Hotkey, If

01 May 2020, 20:42

Delta Pythagorean wrote:
01 May 2020, 19:51
I have a few questions:
  1. Why are you forcing Global inside of a function that doesn't need global?
  2. Is there a particular reason why are you using SendEvent versus something else?
  3. Why do you have a function dedicated to returning whether notepad++ is active? Why not just put the WinActive call on the same line?
  4. What build of AHK are you using? Are you using Unicode or ANSI?
  5. Since you said you couldn't test it in AHK_L are you using AHK_H?
Hello, answering them on the same order:
  1. It's there only because I was testing stuff.
  2. SendInput is buggy. If you use it on that specific code you will see it breaks the while a lot of times and also makes it get stuck.
  3. Same as 1. Part of some tests I made, the first thing I used was #ifWinActive and had the same results, I posted the last code I tested.
  4. Unicode both x32 and x64 have the same problem. Latest version
  5. Yes, latest version of AHK_H. I originally posted on ahk_h's forum as I couldn't test it on ahk_l.
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Confirmed bug with #if and Hotkey, If  Topic is solved

02 May 2020, 10:42

the hotkey runs only when the condition is satisfied. WinActive and WinExist return the hwnd of the found window. at some point in time, for some reason, this hwnd(example: L"0x1e32ce") ends up in sDerefBuf(see ballpark) as the udf sendKey_f is just about to begin execution(see further below, call to ExpandExpression). Some calls later, the hwnd gets parsed by SendKeys always truncating the leading 3 chars(eg L"0x1") and sending the remaining ones(L"e32ce"), which is what u then see occasionally printed in notepad

if avoid using WinActive tail calls, there is no problem:

Code: Select all

notepadActive() {
	hwnd := WinActive("ahk_exe notepad.exe")
	return hwnd
}

notepadActive() {
	if WinActive("ahk_exe notepad.exe")
		return true
}
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: Confirmed bug with #if and Hotkey, If

02 May 2020, 13:39

swagfag wrote:
02 May 2020, 10:42
the hotkey runs only when the condition is satisfied. WinActive and WinExist return the hwnd of the found window. at some point in time, for some reason, this hwnd(example: L"0x1e32ce") ends up in sDerefBuf(see ballpark) as the udf sendKey_f is just about to begin execution(see further below, call to ExpandExpression). Some calls later, the hwnd gets parsed by SendKeys always truncating the leading 3 chars(eg L"0x1") and sending the remaining ones(L"e32ce"), which is what u then see occasionally printed in notepad

if avoid using WinActive tail calls, there is no problem:

Code: Select all

notepadActive() {
	hwnd := WinActive("ahk_exe notepad.exe")
	return hwnd
}

notepadActive() {
	if WinActive("ahk_exe notepad.exe")
		return true
}
That's good info. Thank you! I will use the workaround for now, what a weird bug haha
guest3456
Posts: 3463
Joined: 09 Oct 2013, 10:31

Re: Confirmed bug with #if and Hotkey, If

02 May 2020, 21:27

good work swagfag

Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Confirmed bug with #if and Hotkey, If

16 May 2020, 08:14

swagfag wrote: at some point in time, for some reason, this hwnd(example: L"0x1e32ce") ends up in sDerefBuf(see ballpark) as the udf sendKey_f is just about to begin execution(see further below, call to ExpandExpression). Some calls later, the hwnd gets parsed by SendKeys always truncating the leading 3 chars(eg L"0x1") and sending the remaining ones
It ends up in the deref buffer when the hotkey context callback interrupts the send command. If the send command is interrupted after it has sent {a}, it has parsed three characters, hence the truncation of "0x1".
if avoid using WinActive tail calls, there is no problem
Anything in the context callback which changes the deref buffer can corrupt the send commands parameter, eg,

Code: Select all

testbug:
	sendEvent % "{a}"
return
notepadActive()
{
	setwindelay % "0x12345"
	h := WinActive("ahk_exe notepad++.exe")
	return h
}
; aaaa2345a23450x12345a2345a23450x123450x12345aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
A more reliable work around (I guess) would be to priviatise the send parameter,

Code: Select all

testbug:
	a := "{a}"
	sendEvent %a%
return
But be aware that if the interruption changes the variable a during the send you might get into trouble, please use a local variable instead.
but it won't happen if you:
1. Replace the function call with sendEvent
2. Replace the sendEvent inside the function with sendInput (but this gives other issues)
1. It can, but since this bug requires some timing, it might not for you.
2. It might be possible that it can happen with sendinput even if it doesn't revert to sendevent, if the send command is interrupted before it has parsed the entire input. It is evidently possible for sendevent, since my example above produced the full "0x12345".

This can probably also happen with interruptions from callbacks created with registercallback.

Cheers.
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: Confirmed bug with #if and Hotkey, If

22 May 2020, 20:48

Helgef wrote:It might be possible that it can happen with sendinput even if it doesn't revert to sendevent, if the send command is interrupted before it has parsed the entire input.
In their native modes, SendInput and SendPlay parse the entire Keys parameter before any keys are sent (and there should be no possibility of interruption up to that point), so they should be unaffected by any changes to the deref buffer caused by an interruption. SendInput is less likely to be interrupted since it temporarily uninstalls the keyboard hook before actually sending any keys.

SendEvent is much more prone to interruption because it specifically pumps messages (it sleeps) between key events.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Confirmed bug with #if and Hotkey, If

23 May 2020, 00:23

I thought maybe an interruption could occur before parsing, such as when waiting for the win key to be released. There's a lot going on in those parts of the implementation, I'm very happy to be ignorant about it :) .

Cheers.
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: Confirmed bug with #if and Hotkey, If

23 May 2020, 01:05

That's a good point. I was going to say that because the hook is uninstalled, an interruption could only occur if a keyboard event is detected and queues an #if-evaluation message before SendInput begins sending keys, but not in time for it to be processed by the script's previous check for messages. Then the message would also need to be processed before SendInput finishes parsing its parameter, but since I couldn't think of any reason for that to happen (such as the Win-L workaround), I didn't mention it.

Actually, the hook being uninstalled is probably irrelevant because it is done after the parameter is parsed.

Anyway, I suppose it's much less likely to happen with SendInput (in its native mode), due to the timing requirements and the conditions which must be met to cause interruption (for instance, this hotkey doesn't use the Win key or attempt to send the L key).

Return to “Bug Reports”

Who is online

Users browsing this forum: No registered users and 62 guests