Skip to content

Commit

Permalink
Merge pull request #258 from spyoungtech/gh-257
Browse files Browse the repository at this point in the history
Add AHK process handling to exit if parent Python process dies unexpectedly
  • Loading branch information
spyoungtech committed Feb 7, 2024
2 parents 84e8ab3 + 065581d commit 7680da8
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 20 deletions.
56 changes: 47 additions & 9 deletions ahk/_constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -2756,6 +2756,7 @@
{% endfor %}
; END extension scripts
{% block before_autoexecute %}
{% endblock before_autoexecute %}
Expand All @@ -2765,6 +2766,15 @@
Loop {
query := RTrim(stdin.ReadLine(), "`n")
if (query = "") {
; Technically this should only happen if the Python process has died, so sending a message is probably futile
; But if this somehow triggers in some other case, we'll try to have an informative error raised.
pyresp := FormatResponse("ahk.message.ExceptionResponseMessage", "Unexpected empty message; AHK exiting. This is likely a bug. Please report this issue at https://github.com/spyoungtech/ahk/issues")
FileAppend, %pyresp%, *, UTF-8
; Exit to avoid leaving the process hanging around needlessly
ExitApp
}
argsArray := CommandArrayFromQuery(query)
try {
func := argsArray[1]
Expand Down Expand Up @@ -2796,6 +2806,7 @@

HOTKEYS_SCRIPT_TEMPLATE = r"""#Requires AutoHotkey v1.1.17+
#Persistent
{% for directive in directives %}
{% if directive.apply_to_hotkeys_process %}
Expand All @@ -2807,7 +2818,8 @@
OnClipboardChange("ClipChanged")
{% endif %}
KEEPALIVE := Chr(57344)
SetTimer, keepalive, 1000
stdin := FileOpen("*", "r `n", "UTF-8")
SetTimer, keepalive, 2000
Crypt32 := DllCall("LoadLibrary", "Str", "Crypt32.dll", "Ptr")
Expand Down Expand Up @@ -2892,8 +2904,16 @@
keepalive:
global KEEPALIVE
FileAppend, %KEEPALIVE%`n, *, UTF-8
global KEEPALIVE
global stdin
FileAppend, %KEEPALIVE%`n, *, UTF-8
alive_message := RTrim(stdin.ReadLine(), "`n")
if (alive_message != KEEPALIVE) {
; The parent Python process has terminated unexpectedly
; Exit to avoid leaving the hotkey process around
ExitApp
}
return
"""

Expand Down Expand Up @@ -5744,6 +5764,15 @@
Loop {
query := RTrim(stdin.ReadLine(), "`n")
if (query = "") {
; Technically, this should only happen if the Python process has died, so sending a message is probably futile
; But if this somehow triggers in some other case and the Python process is still listening, we'll try to have an informative error raised.
pyresp := FormatResponse("ahk.message.ExceptionResponseMessage", "Unexpected empty message; AHK exiting. This is likely a bug. Please report this issue at https://github.com/spyoungtech/ahk/issues")
stdout.Write(pyresp)
stdout.Read(0)
; Exit to avoid leaving the process hanging around
ExitApp
}
argsArray := CommandArrayFromQuery(query)
try {
func_name := argsArray[1]
Expand Down Expand Up @@ -5786,9 +5815,9 @@
KEEPALIVE := Chr(57344)
;SetTimer, keepalive, 1000
stdout := FileOpen("*", "w", "UTF-8")
stdin := FileOpen("*", "r `n", "UTF-8")
WriteStdout(s) {
global stdout
Expand Down Expand Up @@ -5883,10 +5912,19 @@
OnClipboardChange(ClipChanged)
{% endif %}
;keepalive:
;global KEEPALIVE
;FileAppend, %KEEPALIVE%`n, *, UTF-8
SetTimer KeepAliveFunc, 2000
KeepAliveFunc() {
global stdin
global KEEPALIVE
WriteStdout(Format("{}`n", KEEPALIVE))
alive_message := RTrim(stdin.ReadLine(), "`n")
if (alive_message != KEEPALIVE) {
; The parent Python process has terminated unexpectedly
; Exit to avoid leaving the hotkey process around
ExitApp
}
return
}
"""
5 changes: 4 additions & 1 deletion ahk/_hotkey.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,11 +336,14 @@ def listener(self) -> None:
stderr=subprocess.STDOUT,
)
atexit.register(kill, self._proc)
assert self._proc.stdout is not None
assert self._proc.stdin is not None
while self._running:
assert self._proc.stdout is not None
line = self._proc.stdout.readline()
if line.rstrip(b'\n') == _KEEPALIVE_SENTINEL:
logging.debug('keepalive received')
self._proc.stdin.write(b'\xee\x80\x80\n')
self._proc.stdin.flush()
continue
if not line.strip():
logging.debug('Listener: Process probably died, exiting')
Expand Down
9 changes: 9 additions & 0 deletions ahk/templates/daemon-v2.ahk
Original file line number Diff line number Diff line change
Expand Up @@ -2845,6 +2845,15 @@ pyresp := ""

Loop {
query := RTrim(stdin.ReadLine(), "`n")
if (query = "") {
; Technically, this should only happen if the Python process has died, so sending a message is probably futile
; But if this somehow triggers in some other case and the Python process is still listening, we'll try to have an informative error raised.
pyresp := FormatResponse("ahk.message.ExceptionResponseMessage", "Unexpected empty message; AHK exiting. This is likely a bug. Please report this issue at https://github.com/spyoungtech/ahk/issues")
stdout.Write(pyresp)
stdout.Read(0)
; Exit to avoid leaving the process hanging around
ExitApp
}
argsArray := CommandArrayFromQuery(query)
try {
func_name := argsArray[1]
Expand Down
10 changes: 10 additions & 0 deletions ahk/templates/daemon.ahk
Original file line number Diff line number Diff line change
Expand Up @@ -2753,6 +2753,7 @@ CommandArrayFromQuery(ByRef text) {

{% endfor %}
; END extension scripts

{% block before_autoexecute %}
{% endblock before_autoexecute %}

Expand All @@ -2762,6 +2763,15 @@ pyresp := ""

Loop {
query := RTrim(stdin.ReadLine(), "`n")
if (query = "") {
; Technically this should only happen if the Python process has died, so sending a message is probably futile
; But if this somehow triggers in some other case, we'll try to have an informative error raised.
pyresp := FormatResponse("ahk.message.ExceptionResponseMessage", "Unexpected empty message; AHK exiting. This is likely a bug. Please report this issue at https://github.com/spyoungtech/ahk/issues")
FileAppend, %pyresp%, *, UTF-8

; Exit to avoid leaving the process hanging around needlessly
ExitApp
}
argsArray := CommandArrayFromQuery(query)
try {
func := argsArray[1]
Expand Down
21 changes: 15 additions & 6 deletions ahk/templates/hotkeys-v2.ahk
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@


KEEPALIVE := Chr(57344)
;SetTimer, keepalive, 1000

stdout := FileOpen("*", "w", "UTF-8")
stdin := FileOpen("*", "r `n", "UTF-8")

WriteStdout(s) {
global stdout
Expand Down Expand Up @@ -105,8 +105,17 @@ ClipChanged(Type) {
OnClipboardChange(ClipChanged)

{% endif %}


;keepalive:
;global KEEPALIVE
;FileAppend, %KEEPALIVE%`n, *, UTF-8
SetTimer KeepAliveFunc, 2000

KeepAliveFunc() {
global stdin
global KEEPALIVE
WriteStdout(Format("{}`n", KEEPALIVE))
alive_message := RTrim(stdin.ReadLine(), "`n")
if (alive_message != KEEPALIVE) {
; The parent Python process has terminated unexpectedly
; Exit to avoid leaving the hotkey process around
ExitApp
}
return
}
16 changes: 13 additions & 3 deletions ahk/templates/hotkeys.ahk
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#Requires AutoHotkey v1.1.17+
#Persistent

{% for directive in directives %}
{% if directive.apply_to_hotkeys_process %}

Expand All @@ -11,7 +12,8 @@
OnClipboardChange("ClipChanged")
{% endif %}
KEEPALIVE := Chr(57344)
SetTimer, keepalive, 1000
stdin := FileOpen("*", "r `n", "UTF-8")
SetTimer, keepalive, 2000

Crypt32 := DllCall("LoadLibrary", "Str", "Crypt32.dll", "Ptr")

Expand Down Expand Up @@ -96,5 +98,13 @@ ClipChanged(Type) {


keepalive:
global KEEPALIVE
FileAppend, %KEEPALIVE%`n, *, UTF-8
global KEEPALIVE
global stdin
FileAppend, %KEEPALIVE%`n, *, UTF-8
alive_message := RTrim(stdin.ReadLine(), "`n")
if (alive_message != KEEPALIVE) {
; The parent Python process has terminated unexpectedly
; Exit to avoid leaving the hotkey process around
ExitApp
}
return
3 changes: 2 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ print(ahk.mouse_position) # (150, 150)

# Examples

Non-exhaustive examples of some functions available with this package. Full documentation coming soon!
Non-exhaustive examples of some functions available with this package. See the [full documentation](https://ahk.readthedocs.io/en/latest/?badge=latest)
for complete API references and additional features.

## Hotkeys

Expand Down

0 comments on commit 7680da8

Please sign in to comment.