fix(desktop): keep serve backend alive through Windows launcher
This commit is contained in:
parent
6a20383eeb
commit
1edfdeee81
|
|
@ -17696,9 +17696,26 @@ def _maybe_open_browser(
|
|||
threading.Thread(target=_open, daemon=True).start()
|
||||
|
||||
|
||||
def _is_serve_orphaned(original_ppid: int, getppid=os.getppid) -> bool:
|
||||
"""True when this process lost its original spawning parent (ppid changed)."""
|
||||
return getppid() != original_ppid
|
||||
def _is_serve_orphaned(desktop_pid: int, pid_exists=None) -> bool:
|
||||
"""True when the Desktop process that owns this serve backend is gone.
|
||||
|
||||
``HERMES_PARENT_PID`` is the Electron Desktop PID, not necessarily this
|
||||
Python process's immediate PPID. On Windows the venv ``hermes.exe`` launcher
|
||||
introduces one or more shim processes, so comparing ``os.getppid()`` to the
|
||||
Electron PID incorrectly treats a healthy backend as orphaned and exits 0.
|
||||
Probe the recorded Desktop PID directly instead.
|
||||
|
||||
Any liveness-probe failure is fail-safe: keep serving rather than killing a
|
||||
backend whose owner could not be conclusively shown to be dead.
|
||||
"""
|
||||
try:
|
||||
if pid_exists is None:
|
||||
from gateway.status import _pid_exists
|
||||
|
||||
pid_exists = _pid_exists
|
||||
return not bool(pid_exists(int(desktop_pid)))
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def _start_parent_death_watchdog() -> None:
|
||||
|
|
@ -17716,7 +17733,7 @@ def _start_parent_death_watchdog() -> None:
|
|||
if not raw:
|
||||
return
|
||||
try:
|
||||
original_ppid = int(raw)
|
||||
desktop_pid = int(raw)
|
||||
except (TypeError, ValueError):
|
||||
return
|
||||
try:
|
||||
|
|
@ -17725,7 +17742,7 @@ def _start_parent_death_watchdog() -> None:
|
|||
poll = 2.0
|
||||
|
||||
def _loop() -> None:
|
||||
while not _is_serve_orphaned(original_ppid):
|
||||
while not _is_serve_orphaned(desktop_pid):
|
||||
time.sleep(poll)
|
||||
os._exit(0)
|
||||
|
||||
|
|
@ -17733,9 +17750,8 @@ def _start_parent_death_watchdog() -> None:
|
|||
|
||||
|
||||
def _demo() -> None:
|
||||
# orphan iff current ppid differs from the recorded spawning parent
|
||||
assert _is_serve_orphaned(999999999, getppid=lambda: 1) is True
|
||||
assert _is_serve_orphaned(42, getppid=lambda: 42) is False
|
||||
assert _is_serve_orphaned(999999999, pid_exists=lambda _pid: False) is True
|
||||
assert _is_serve_orphaned(42, pid_exists=lambda _pid: True) is False
|
||||
print("web_server parent-death watchdog self-check: OK")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
"""Regression tests for Desktop-owned ``hermes serve`` lifecycle tracking."""
|
||||
|
||||
from hermes_cli.web_server import _is_serve_orphaned
|
||||
|
||||
|
||||
def test_parent_watchdog_tracks_recorded_desktop_pid_not_immediate_ppid():
|
||||
"""Windows venv launch shims must not make a live Desktop look orphaned."""
|
||||
|
||||
assert _is_serve_orphaned(4242, pid_exists=lambda pid: pid == 4242) is False
|
||||
assert _is_serve_orphaned(4242, pid_exists=lambda _pid: False) is True
|
||||
|
||||
|
||||
def test_parent_watchdog_fails_safe_when_liveness_probe_errors():
|
||||
def broken_probe(_pid: int) -> bool:
|
||||
raise OSError("process table temporarily unavailable")
|
||||
|
||||
assert _is_serve_orphaned(4242, pid_exists=broken_probe) is False
|
||||
Loading…
Reference in New Issue