fix(tui): the legacy slash-worker watchdog flushes the opt-in metrics before os._exit

Rebase onto main: main's 7c4e069596 (teknium, Oct 25) added flush_before_hard_exit() before the
slash worker's parent-death os._exit, so an orphaned worker still writes the open sessions'
summary for the opt-in metrics runtimes. This branch replaced that watchdog with the owner-death
supervisor and keeps only a legacy one for a worker a pre-update gateway launched with
--parent-pid; that one now flushes too. main's test drove the removed watchdog; it now drives the
legacy one (POSIX only, like the watchdog).

Test: test_orphaned_slash_worker_writes_the_open_sessions_summary fails with the flush removed.
This commit is contained in:
kshitijk4poor authored and kshitij committed 2026-10-29 16:58:09 +05:30
1 parent fc67e99e99
commit 3460122ede
2 files changed
+6 -3

No files matched your search

@@ -153,6 +153,7 @@ def test_sigtermed_kanban_worker_writes_the_open_sessions_summary(metrics_home,
assert "hermes.session.count" in _metric_names(home)
@pytest.mark.skipif(os.name != "posix", reason="the legacy parent watchdog is POSIX-only")
def test_orphaned_slash_worker_writes_the_open_sessions_summary(metrics_home, monkeypatch):
from tui_gateway import slash_worker
@@ -160,10 +161,10 @@ def test_orphaned_slash_worker_writes_the_open_sessions_summary(metrics_home, mo
_finished_task_in_open_session()
_wait_for(home, "hermes.task_run.finished")
exited = threading.Event()
monkeypatch.setattr(slash_worker, "_is_orphaned", lambda ppid: True)
monkeypatch.setattr(slash_worker.os, "_exit", lambda code: exited.set())
slash_worker._start_parent_death_watchdog(1)
# A worker a pre-update gateway launched (--parent-pid) whose parent is gone: the live ppid differs.
slash_worker._start_legacy_parent_watchdog(os.getppid() + 1_000_000, poll_s=0.01, grace_s=0)
assert exited.wait(10)
assert "hermes.session.count" in _metric_names(home)
+3 -1
View File
@@ -56,9 +56,11 @@ def _start_legacy_parent_watchdog(parent_pid: int, *, poll_s: float = 2.0, grace
deadline = time.monotonic() + grace_s
while _in_flight.is_set() and time.monotonic() < deadline:
time.sleep(0.05)
from hermes_cli.observability.shared_metrics_process import flush_before_hard_exit
flush_before_hard_exit() # os._exit skips the opt-in metrics runtimes' atexit flush (bounded)
os._exit(0)
# health: allow HX012 -- the loop only reads getppid() and calls os._exit; no profile-scoped state
# health: allow HX012 -- the loop reads getppid(), flushes the opt-in metrics and calls os._exit
threading.Thread(target=_loop, daemon=True, name="slash-legacy-parent-watchdog").start()