mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-31 19:16:29 +00:00
fix(tui): use direct parent identity in slash worker
Remove process creation time and pid_exists from the slash worker parent-death predicate. The worker remains attached while its original PPID matches and keeps the existing in-flight grace behavior.\n\nRefs #62505
This commit is contained in:
parent
3d031bdb29
commit
68f7f15207
2 changed files with 20 additions and 32 deletions
|
|
@ -1,21 +1,24 @@
|
|||
import psutil
|
||||
import inspect
|
||||
|
||||
from tui_gateway import slash_worker
|
||||
|
||||
|
||||
def test_is_orphaned_true_when_ppid_changes():
|
||||
# Our parent went away and we were reparented to a subreaper/init.
|
||||
assert slash_worker._is_orphaned(1234, 1.0, getppid=lambda: 999999) is True
|
||||
assert slash_worker._is_orphaned(1234, getppid=lambda: 999999) is True
|
||||
|
||||
|
||||
def test_is_orphaned_true_when_parent_create_time_mismatch():
|
||||
# Same ppid but a different create_time means the PID was reused.
|
||||
me = psutil.Process()
|
||||
assert slash_worker._is_orphaned(me.pid, 0.0, getppid=lambda: me.pid) is True
|
||||
def test_is_orphaned_false_when_direct_parent_is_unchanged():
|
||||
original_ppid = 1234
|
||||
assert slash_worker._is_orphaned(original_ppid, getppid=lambda: original_ppid) is False
|
||||
|
||||
|
||||
def test_is_orphaned_false_when_parent_alive_and_matches():
|
||||
me = psutil.Process()
|
||||
assert (
|
||||
slash_worker._is_orphaned(me.pid, me.create_time(), getppid=lambda: me.pid) is False
|
||||
)
|
||||
def test_parent_death_watchdog_contract_has_no_create_time_plumbing():
|
||||
assert list(inspect.signature(slash_worker._is_orphaned).parameters) == [
|
||||
"original_ppid",
|
||||
"getppid",
|
||||
]
|
||||
assert list(inspect.signature(slash_worker._start_parent_death_watchdog).parameters) == [
|
||||
"original_ppid",
|
||||
]
|
||||
assert "psutil" not in slash_worker.__dict__
|
||||
|
|
|
|||
|
|
@ -25,8 +25,6 @@ import sys
|
|||
import threading
|
||||
import time
|
||||
|
||||
import psutil
|
||||
|
||||
import cli as cli_mod
|
||||
from cli import HermesCLI
|
||||
from rich.console import Console
|
||||
|
|
@ -51,18 +49,9 @@ _ORPHAN_GRACE_S = max(0.0, _env_float("HERMES_SLASH_WATCHDOG_GRACE_S", 5.0))
|
|||
_in_flight = threading.Event() # set while a command is executing
|
||||
|
||||
|
||||
def _is_orphaned(original_ppid, parent_create_time, getppid=os.getppid) -> bool:
|
||||
"""True once our spawning gateway is gone. Compare to the ORIGINAL ppid
|
||||
(never ==1: Linux reparents to a subreaper) and guard PID reuse via
|
||||
create_time."""
|
||||
if getppid() != original_ppid:
|
||||
return True
|
||||
try:
|
||||
if not psutil.pid_exists(original_ppid):
|
||||
return True
|
||||
return psutil.Process(original_ppid).create_time() != parent_create_time
|
||||
except psutil.Error:
|
||||
return True
|
||||
def _is_orphaned(original_ppid, getppid=os.getppid) -> bool:
|
||||
"""Return whether this worker no longer has its original POSIX parent."""
|
||||
return getppid() != original_ppid
|
||||
|
||||
|
||||
def _prepare_slash_worker_runtime() -> None:
|
||||
|
|
@ -86,9 +75,9 @@ def _prepare_slash_worker_runtime() -> None:
|
|||
wait_for_mcp_discovery()
|
||||
|
||||
|
||||
def _start_parent_death_watchdog(original_ppid, parent_create_time) -> None:
|
||||
def _start_parent_death_watchdog(original_ppid) -> None:
|
||||
def _loop():
|
||||
while not _is_orphaned(original_ppid, parent_create_time):
|
||||
while not _is_orphaned(original_ppid):
|
||||
time.sleep(_WATCHDOG_POLL_S)
|
||||
deadline = time.monotonic() + _ORPHAN_GRACE_S
|
||||
while _in_flight.is_set() and time.monotonic() < deadline:
|
||||
|
|
@ -145,11 +134,7 @@ def main():
|
|||
# Start before the (hundreds-of-ms) HermesCLI build — that window is itself
|
||||
# an orphan risk if the gateway dies mid-spawn.
|
||||
orig_ppid = os.getppid()
|
||||
try:
|
||||
parent_create_time = psutil.Process(orig_ppid).create_time()
|
||||
except psutil.Error:
|
||||
parent_create_time = 0.0
|
||||
_start_parent_death_watchdog(orig_ppid, parent_create_time)
|
||||
_start_parent_death_watchdog(orig_ppid)
|
||||
_prepare_slash_worker_runtime()
|
||||
|
||||
with contextlib.redirect_stdout(io.StringIO()), contextlib.redirect_stderr(io.StringIO()):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue