Skip to content

fix(tui): close slash_worker inside _finalize_session (defense-in-depth, #38095)#42149

Merged
teknium1 merged 1 commit into
mainfrom
hermes/hermes-9af29c1e
Jun 8, 2026
Merged

fix(tui): close slash_worker inside _finalize_session (defense-in-depth, #38095)#42149
teknium1 merged 1 commit into
mainfrom
hermes/hermes-9af29c1e

Conversation

@teknium1

@teknium1 teknium1 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Closing the TUI slash-worker subprocess is now a side effect of _finalize_session itself — the single _finalized-guarded session-end chokepoint — so no session-end path can leak the worker.

The active leak #38095 reported was already fixed on main (WS-orphan reaper from #38591, _restart_slash_worker closing the old worker, atexit _shutdown_sessions). This addresses the residual defense-in-depth gap the reporter correctly identified in their follow-up comment: worker cleanup lived only in the callers, so a future code path that calls _finalize_session() directly would silently re-leak.

Changes

  • tui_gateway/server.py: _finalize_session() now closes session["slash_worker"] as its last step. Updated _teardown_session docstring; dropped the now-redundant separate worker.close() in _shutdown_sessions.
  • tests/test_tui_gateway_server.py: regression test — _finalize_session closes the worker exactly once and is idempotent across repeat finalize + follow-up teardown.

Idempotent by construction: _SlashWorker.close() is poll()-guarded and _finalize_session short-circuits on _finalized, so existing teardown paths (session.close, WS-orphan reap, shutdown) behave identically.

Validation

Before After
_finalize_session direct call worker leaks worker closed
session.close / WS reap / shutdown worker closed worker closed (single path)
double finalize + teardown n/a worker closed exactly once
tests/test_tui_gateway_server.py 215 passed 223 passed (+new test)

Closes #38095.

Infographic

slash-worker-leak-sealed

…th, #38095)

Fold the slash-worker subprocess close into _finalize_session itself —
the single _finalized-guarded session-end chokepoint — instead of
relying on each caller (_teardown_session, _shutdown_sessions) to close
it separately. A future code path that finalizes a session directly can
no longer reintroduce the #38095 worker leak.

Idempotent: _SlashWorker.close() is poll()-guarded and _finalize_session
short-circuits on _finalized, so the existing teardown paths are
unaffected. Drops the now-redundant separate close() in
_shutdown_sessions.

Note: the active leak this issue reported was already fixed on main
(WS-orphan reaper #38591, _restart_slash_worker close, atexit shutdown).
This addresses the residual defense-in-depth gap the reporter correctly
identified in their follow-up comment.
@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

🔎 Lint report: hermes/hermes-9af29c1e vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 10399 on HEAD, 10399 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 5432 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@teknium1 teknium1 merged commit a3fca26 into main Jun 8, 2026
23 checks passed
@teknium1 teknium1 deleted the hermes/hermes-9af29c1e branch June 8, 2026 14:26
jhjaggars-hermes pushed a commit to jhjaggars/hermes-agent that referenced this pull request Jun 8, 2026
…th, NousResearch#38095) (NousResearch#42149)

Fold the slash-worker subprocess close into _finalize_session itself —
the single _finalized-guarded session-end chokepoint — instead of
relying on each caller (_teardown_session, _shutdown_sessions) to close
it separately. A future code path that finalizes a session directly can
no longer reintroduce the NousResearch#38095 worker leak.

Idempotent: _SlashWorker.close() is poll()-guarded and _finalize_session
short-circuits on _finalized, so the existing teardown paths are
unaffected. Drops the now-redundant separate close() in
_shutdown_sessions.

Note: the active leak this issue reported was already fixed on main
(WS-orphan reaper NousResearch#38591, _restart_slash_worker close, atexit shutdown).
This addresses the residual defense-in-depth gap the reporter correctly
identified in their follow-up comment.
a249169329-cpu pushed a commit to a249169329-cpu/hermes-agent that referenced this pull request Jun 9, 2026
…th, NousResearch#38095) (NousResearch#42149)

Fold the slash-worker subprocess close into _finalize_session itself —
the single _finalized-guarded session-end chokepoint — instead of
relying on each caller (_teardown_session, _shutdown_sessions) to close
it separately. A future code path that finalizes a session directly can
no longer reintroduce the NousResearch#38095 worker leak.

Idempotent: _SlashWorker.close() is poll()-guarded and _finalize_session
short-circuits on _finalized, so the existing teardown paths are
unaffected. Drops the now-redundant separate close() in
_shutdown_sessions.

Note: the active leak this issue reported was already fixed on main
(WS-orphan reaper NousResearch#38591, _restart_slash_worker close, atexit shutdown).
This addresses the residual defense-in-depth gap the reporter correctly
identified in their follow-up comment.
changman pushed a commit to changman/hermes-agent that referenced this pull request Jun 10, 2026
…th, NousResearch#38095) (NousResearch#42149)

Fold the slash-worker subprocess close into _finalize_session itself —
the single _finalized-guarded session-end chokepoint — instead of
relying on each caller (_teardown_session, _shutdown_sessions) to close
it separately. A future code path that finalizes a session directly can
no longer reintroduce the NousResearch#38095 worker leak.

Idempotent: _SlashWorker.close() is poll()-guarded and _finalize_session
short-circuits on _finalized, so the existing teardown paths are
unaffected. Drops the now-redundant separate close() in
_shutdown_sessions.

Note: the active leak this issue reported was already fixed on main
(WS-orphan reaper NousResearch#38591, _restart_slash_worker close, atexit shutdown).
This addresses the residual defense-in-depth gap the reporter correctly
identified in their follow-up comment.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: TUI slash worker subprocesses leak after session close, accumulating zombie processes

1 participant