Repository navigation
fix(gateway): self-heal state file PID on server startup - #4547
Conversation
fix(gateway): self-heal state file PID on server startup After /restart on Windows, the gateway process gets a new PID (os.execv creates a new process on Windows), but the state file at run/gateway.<suffix>.json still contains the old PID from the initial background spawn. Nothing rewrites it, leaving state inconsistent. Add GatewayRuntime.refresh_state_pid() — a classmethod that reads the existing state file, updates the PID and identity to the current process, and writes atomically. Call it early in _run_gateway() so the state file is always correct regardless of how the process was started (initial spawn, os.execv, or subprocess.Popen). On POSIX os.execv preserves the PID, so this is a no-op in normal operation there, but still beneficial after any unusual restart path. Fixes HKUDS#4511 @
chengyongru
left a comment
There was a problem hiding this comment.
Automated PR review by nanobot. This is not a human maintainer review or approval.
This change addresses the issue where the gateway state file retains a stale PID from a previous process (common on Windows where os.execv is unavailable and the gateway restarts as a new process). The fix adds GatewayRuntime.refresh_state_pid() — called early in _run_gateway — which reads the existing state file and overwrites pid, identity, and started_at with current values.
What's good
- Called early in
_run_gateway(), before any significant server setup, so the state file is consistent from the start. - Handles the no-state-file case (first launch) gracefully by returning early.
- Safe I/O:
json.loadswithexcept (json.JSONDecodeError, OSError)covers corrupt file and permission errors. - Uses
rt._write_state(state)for atomic write, consistent with existing state writing conventions. - The
GatewayRuntimePaths.for_instance()creation incommands.pycorrectly handles theworkspacevsconfig_pathcase.
No issues found.
Re-bin
left a comment
There was a problem hiding this comment.
LGTM. This fixes stale gateway runtime state after a restarted or spawned foreground gateway by refreshing the stored pid, identity, and start time early in startup, while leaving missing or corrupt state files as no-ops. The change stays inside gateway runtime state handling and does not disturb channel startup.
Validated locally:
python -m pytest tests/gateway/test_runtime.py tests/cli/test_gateway_commands.py tests/cli/test_commands.py::test_webui_background_starts_runtime_and_opens_browser -qpython -m ruff check nanobot/gateway/runtime.py nanobot/cli/commands.py
@
Summary
Fixes #4511 — after
/restarton Windows, the gateway state file (run/gateway.<suffix>.json) keeps the old PID. On POSIX,os.execvpreserves the PID so this is invisible; on Windows, the process gets a new PID but the state file is never updated.Changes
nanobot/gateway/runtime.pyGatewayRuntime.refresh_state_pid()classmethod that reads the existing state file, updates PID / identity / started_at to the current process, and writes atomically via_write_state.nanobot/cli/commands.py_run_gateway(), callGatewayRuntime.refresh_state_pid()early in startup (after config is loaded, before the server starts listening). This self-heals the state file on every gateway start, regardless of platform or restart mechanism.Verification
ruff check— cleanpytest tests/command/— 39 passed@