mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-11-06 05:17:15 +00:00
The session-end reaper (78eff4628a, #106742) found leftover processes by
reading /proc/<pid>/environ, so on macOS it scanned nothing. There, e2e
tests that make a client start its own gateway (e.g. the C7 two-tenant
Desktop backend) leave a `gateway run --idle-exit` daemon running as a
launchd job, outside the pytest process tree. The test homes configure
an API server, so the gateway's idle exit keeps reporting
"messaging ['api_server']" and the daemon never exits: ~320 MB per run.
One dev Mac had 22 of them, 11-26 h old.
Read each process's exec-time environment through psutil on every POSIX
host instead, and run the reaper's own test on macOS. That test times
out on base on macOS and passes here; a real C7 run leaves no gateway
behind afterwards.
48 lines
2.1 KiB
Python
48 lines
2.1 KiB
Python
"""The session teardown stops processes left running against this run's Hermes homes.
|
|
|
|
A test that runs a real ``hermes chat -q`` child gets a grandchild ``gateway run`` in its own
|
|
session; no per-test subprocess patch sees it, and pytest's tmp cleanup removes only directories.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
|
|
from tests import conftest as suite_conftest
|
|
from tests.waiting import wait_until
|
|
|
|
|
|
def _detached(env_home, marker):
|
|
code = "import time\nwhile True: time.sleep(0.2)\n"
|
|
env = {**os.environ, "HERMES_HOME": str(env_home), "LIVE_REAP_MARKER": marker}
|
|
return subprocess.Popen([sys.executable, "-c", code], env=env, start_new_session=True,
|
|
stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
|
|
|
|
@pytest.mark.platforms("linux", "macos")
|
|
@pytest.mark.live_system_guard_bypass # signals only the two children this test spawned
|
|
def test_session_teardown_terminates_daemons_under_the_session_basetemp_only(tmp_path):
|
|
basetemp, elsewhere = tmp_path / "basetemp", tmp_path / "elsewhere"
|
|
(basetemp / "t0" / "hermes").mkdir(parents=True)
|
|
elsewhere.mkdir()
|
|
inside = _detached(basetemp / "t0" / "hermes", "inside")
|
|
outside = _detached(elsewhere, "outside")
|
|
try:
|
|
# Both children have exec'd with their HERMES_HOME (what the reaper reads via psutil environ()).
|
|
wait_until(lambda: {inside.pid, outside.pid} <= set(suite_conftest._processes_with_hermes_home_under(
|
|
[basetemp, elsewhere])), timeout=10, what='both detached children started')
|
|
config = SimpleNamespace(_tmp_path_factory=SimpleNamespace(_basetemp=basetemp))
|
|
reaped = suite_conftest._reap_session_hermes_processes(config)
|
|
assert inside.pid in reaped and outside.pid not in reaped
|
|
assert inside.wait(timeout=5) is not None
|
|
assert outside.poll() is None, "a process outside this session's homes was signalled"
|
|
finally:
|
|
for proc in (inside, outside):
|
|
if proc.poll() is None:
|
|
proc.kill()
|
|
proc.wait(timeout=5)
|