fix(agent): close Codex app-server subprocess on AIAgent.close() (#66671) - #66904
fix(agent): close Codex app-server subprocess on AIAgent.close() (#66671)#66904Enough1122 wants to merge 1 commit into
Conversation
Related to #66678 and broader #55450. The current one-file |
308674d to
36f4cd1
Compare
|
The branch was force-pushed after an earlier triage bot comment ( Current diff is single-file and matches the PR description exactly:
This AI-assisted PR was drafted by Hermes Agent on behalf of @Enough1122. Happy to rebase / split / close if reviewers prefer a different shape. |
|
Thanks for the focused lifecycle repair. The premise is confirmed on current main: Problems
Suggested changes
Automated hermes-sweeper review. |
…sResearch#66671) AIAgent.close() cleaned up background processes, terminal sandboxes, browser daemons, child agents, the OpenAI/httpx client, conversation history, and the SQLite session row — but never closed self._codex_session. The only _codex_session.close() calls lived in crash/retire paths inside agent/codex_runtime.py, so every closed Codex-route session permanently leaked one codex app-server process plus its MCP children. Long-running `hermes serve` deployments accumulated one leaked process tree per closed session. Add a guarded, idempotent close step right after the OpenAI client close, mirroring its try/except + reference-clearing pattern. First call closes and clears the reference; any later call is a no-op. No public API change. Tests: add TestAIAgentCloseCodexSession covering close-and-clear, the no-attribute fallback path, and double-close idempotency. Test shape drawn from closed duplicate NousResearch#66865 as the reviewer's suggested salvage material. Fixes NousResearch#66671.
36f4cd1 to
ffdb0fd
Compare
|
Thanks for the focused salvage guidance on #66904. Updated diff (force-pushed):
Test plan:
No public API change. No new imports. Single defensive step added inside the existing This AI-assisted PR was drafted by Hermes Agent on behalf of @Enough1122. Happy to adjust if reviewers prefer the tests in a different file (e.g. |
|
Per the review's pointer to #66865 (closed duplicate), added
Final diff:
All 3 new tests pass; 26 existing tests unbroken. Branch: |
|
Review feedback addressed —
The branch was force-pushed to a one-file |
|
Closing this PR as it has been labeled |
Summary
AIAgent.close()(inrun_agent.py) cleaned up background processes, terminal sandboxes, browser daemons, child agents, the OpenAI/httpx client, conversation history, and the SQLite session row — but never closedself._codex_session.The only
_codex_session.close()calls in the codebase lived in crash/retire paths insideagent/codex_runtime.py. So every closed Codex-route session permanently leaked onecodex app-serverprocess plus its MCP children. Long-runninghermes servedeployments accumulated one leaked process tree per closed session.Live-verified on v0.18.2 (git c7e09f2) by counting
pgrep -fc "codex app-server"before/aftersession.closecycles. Confirmed unchanged on current main by source inspection.This matches the leak reported in #66671.
Fix
Add a guarded, idempotent close step right after the OpenAI/httpx client close in
AIAgent.close(), mirroring itstry/except+ reference-clearing pattern:First call closes and clears the reference; any later call is a no-op.
CodexAppServerSession.close()(inagent/transports/codex_app_server_session.py) already exists and tears down the subprocess tree + MCP children, so no new code in the transport is needed.Single-file change in
run_agent.py::AIAgent.close. No public API change. No new imports.Test plan
pgrep -fc "codex app-server"andpgrep -fc <MCP binary>.hermes serve, connect via the WebSocket API,session.create, submit one prompt, wait formessage.complete.session.close, wait ~3 seconds.Fixes #66671.