fix(gateway): Windows post-update respawn must mark itself detached (silent gateway death after in-app update) - #53128
Closed
iso2kx wants to merge 1 commit into
Conversation
The post-update gateway respawn watcher (_spawn_gateway_restart_watcher) launched the new gateway without HERMES_GATEWAY_DETACHED=1 and without severing stdin. On Windows, _windows_gateway_should_absorb_console_controls() keys off that env marker (falling back to stdin.isatty()), so the respawned gateway inherited the spawning console, classed itself interactive, and SKIPPED SetConsoleCtrlHandler(NULL, TRUE). It then died silently the instant Windows broadcast CTRL_CLOSE_EVENT / CTRL_LOGOFF_EVENT when the parent console (the post-update desktop shell) went away -- no shutdown log, no traceback. The exit diagnostics confirmed the dead gateway came up with stdin_is_tty=true, absorb_windows_console_controls=false, while every healthy detached gateway shows true. Fix: mirror gateway_windows._spawn_detached in the respawn watcher -- set HERMES_GATEWAY_DETACHED=1 in the child env and redirect stdin to DEVNULL so the respawn installs the console-control guard and survives the desktop console teardown. Covers both respawn paths (profile and unmapped/scheduled -task gateways share this watcher). Adds regression tests asserting the watcher template carries the detached marker and severed stdin.
Contributor
Author
|
Closing as a duplicate of #52239, which already sets The only additive bit here was redirecting the respawn's stdin to DEVNULL as belt-and-braces, in case the env marker is ever dropped. Not worth a separate PR; deferring to #52239. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
On Windows, the post-update gateway respawn watcher launched the new gateway without marking it as a detached service, so the respawned gateway would die silently the moment the spawning console went away — leaving the user with no messaging gateway after an in-app update until a manual restart.
Root cause
_spawn_gateway_restart_watcher(inhermes_cli/gateway.py) respawns the gateway after the old PID exits. On Windows it set the right detach creation flags, but it did not:HERMES_GATEWAY_DETACHED=1in the child env, norDEVNULL._windows_gateway_should_absorb_console_controls()decides whether the gateway installs the console-control guard (SetConsoleCtrlHandler(NULL, TRUE)+SIGINT/SIGBREAKignore). It keys offHERMES_GATEWAY_DETACHED, falling back tosys.stdin.isatty(). Because the respawn carried neither signal, the new gateway inherited the spawning console, classed itself interactive, and skipped the guard.It then died the instant Windows broadcast
CTRL_CLOSE_EVENT/CTRL_LOGOFF_EVENTwhen the parent console (the post-update desktop shell) exited — no shutdown log, no traceback.The gateway exit diagnostics captured the fingerprint exactly: the dead post-update gateway came up with
stdin_is_tty=true, absorb_windows_console_controls=false, whereas every healthy detached gateway (autostart.cmd/_spawn_detached) showstrue.Fix
Mirror the canonical detached launch path (
gateway_windows._spawn_detached) inside the respawn watcher:HERMES_GATEWAY_DETACHED=1in the child env, andDEVNULL(belt-and-braces: even if the env marker were ever dropped, the severed stdin keeps theisatty()fallback from misclassifying it).This covers both respawn paths, since profile gateways (
launch_detached_profile_gateway_restart) and unmapped / Scheduled-Task gateways (launch_detached_gateway_restart_by_cmdline) share this watcher.Tests
Adds
TestGatewayRestartWatcher:test_watcher_marks_respawn_detached_and_severs_stdin— asserts the watcher template sets the detached marker, severs stdin, and passes the env overlay toPopen(and that the template is valid Python).test_by_cmdline_spawns_watcher— asserts the by-cmdline entry point spawns the watcher with the expected argv shape.test_rejects_empty_inputs— guards the early-return validation.No new failures introduced (the pre-existing Linux/Windows-only failures in this file —
signal.SIGKILL, systemd-linger, Docker-root-guard — are unrelated and fail identically on a clean baseline).