mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-08-06 17:38:35 +00:00
@
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 #4511 @
This commit is contained in:
parent
105230cc34
commit
67b56cba74
@ -1306,6 +1306,17 @@ def _run_gateway(
|
|||||||
raise typer.Exit(1) from exc
|
raise typer.Exit(1) from exc
|
||||||
session_manager = SessionManager(config.workspace_path)
|
session_manager = SessionManager(config.workspace_path)
|
||||||
|
|
||||||
|
# Self-heal the gateway state file with the current PID after any restart.
|
||||||
|
from nanobot.gateway.runtime import GatewayRuntime, GatewayRuntimePaths
|
||||||
|
GatewayRuntime.refresh_state_pid(
|
||||||
|
paths=GatewayRuntimePaths.for_instance(
|
||||||
|
workspace=str(config.workspace_path)
|
||||||
|
if not is_default_workspace(config.workspace_path)
|
||||||
|
else None,
|
||||||
|
config_path=config.config_path,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# Preserve existing single-workspace installs, but keep custom workspaces clean.
|
# Preserve existing single-workspace installs, but keep custom workspaces clean.
|
||||||
if is_default_workspace(config.workspace_path):
|
if is_default_workspace(config.workspace_path):
|
||||||
_migrate_cron_store(config)
|
_migrate_cron_store(config)
|
||||||
|
|||||||
@ -127,6 +127,25 @@ class GatewayRuntime:
|
|||||||
self._subprocess_run = subprocess_run
|
self._subprocess_run = subprocess_run
|
||||||
self._sleep = sleep
|
self._sleep = sleep
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def refresh_state_pid(cls, *, paths: GatewayRuntimePaths) -> None:
|
||||||
|
"""Update the PID in an existing state file to ``os.getpid()``.
|
||||||
|
|
||||||
|
Called early in gateway server startup so the state file self-heals
|
||||||
|
after any restart, regardless of platform or restart mechanism.
|
||||||
|
"""
|
||||||
|
if not paths.state_path.exists():
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
state = json.loads(paths.state_path.read_text(encoding="utf-8"))
|
||||||
|
except (json.JSONDecodeError, OSError):
|
||||||
|
return
|
||||||
|
state["pid"] = os.getpid()
|
||||||
|
rt = cls(paths=paths)
|
||||||
|
state["identity"] = rt._process_identity(os.getpid())
|
||||||
|
state["started_at"] = _utc_now()
|
||||||
|
rt._write_state(state)
|
||||||
|
|
||||||
def start_background(self, options: GatewayStartOptions) -> RuntimeResult:
|
def start_background(self, options: GatewayStartOptions) -> RuntimeResult:
|
||||||
"""Start gateway as a detached background process."""
|
"""Start gateway as a detached background process."""
|
||||||
current = self.status()
|
current = self.status()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user