Skip to content

fix(agent): close _codex_session in AIAgent.close() to prevent Codex subprocess leak (#66671) - #66865

Closed
xxiaoxiong wants to merge 1 commit into
NousResearch:mainfrom
xxiaoxiong:fix/66671-codex-session-leak-on-agent-close
Closed

fix(agent): close _codex_session in AIAgent.close() to prevent Codex subprocess leak (#66671)#66865
xxiaoxiong wants to merge 1 commit into
NousResearch:mainfrom
xxiaoxiong:fix/66671-codex-session-leak-on-agent-close

Conversation

@xxiaoxiong

Copy link
Copy Markdown

Summary

Fixes #66671.

AIAgent.close() releases all resources held by an agent instance — background processes, terminal sandboxes, browser daemon sessions, child agents, the OpenAI/httpx client, conversation history, and the SQLite session row — but never closes self._codex_session. The only _codex_session.close() calls in the codebase are the crash/retire paths in agent/codex_runtime.py. Result: every session.close on the Codex app-server route permanently leaks one codex app-server subprocess plus its MCP children. Long-running hermes serve deployments accumulate one leaked process tree per closed session.

Reported on v0.18.2 (c7e09f25); I verified the close path is unchanged on current main.

Fix

Add step 5b in AIAgent.close() that guards _codex_session with getattr (so non-codex agents that never set the attribute are unaffected), calls .close() on it, and sets it to None. Mirrors the existing crash/retire pattern in agent/codex_runtime.py:700-704 and 727-731. Idempotent and individually guarded so a failure here does not suppress the rest of close().

Regression tests

tests/run_agent/test_codex_app_server_integration.py::TestCodexAgentClose:

  • test_close_closes_codex_sessionclose() calls .close() on the codex session and nulls the attribute
  • test_close_handles_missing_codex_session — agent with no _codex_session does not crash (non-codex routes)
  • test_close_idempotent_on_codex_session — double close() only calls .close() once

All 3 tests pass on main with this patch.

tests/run_agent/test_codex_app_server_integration.py::TestCodexAgentClose ...   [100%]
3 passed in 3.78s

Checklist

  • Branch is focused on a single fix
  • Tests added that verify the bug (without the patch, test_close_closes_codex_session and test_close_idempotent_on_codex_session would fail)
  • Idempotent — safe to call multiple times
  • Guarded — non-codex agent paths unaffected
  • No new dependencies

…subprocess leak (NousResearch#66671)

AIAgent.close() cleans up background processes, terminal sandboxes,
browser daemons, child agents, and the OpenAI client — but never
closes self._codex_session. The only _codex_session.close() calls were
the crash/retire paths in codex_runtime.py, meaning every session.close
on the Codex app-server route permanently leaks one codex app-server
process plus its MCP children.

Fix: add step 5b in close() that guards _codex_session with getattr,
calls .close(), and sets it to None. Idempotent and guarded so non-codex
agents (no attr) and double-close both no-op.

Add regression tests:
- test_close_closes_codex_session: close() calls close() and nulls it
- test_close_handles_missing_codex_session: non-codex agent not crash
- test_close_idempotent_on_codex_session: double-close safe

Co-authored-by: teknium1 <127238744+teknium1@users.noreply.github.com>
@alt-glitch alt-glitch added type/bug Something isn't working comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint provider/openai OpenAI / Codex Responses API codex P3 Low — cosmetic, nice to have sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state duplicate This issue or pull request already exists labels Jul 18, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Duplicate of #66678: both add the same AIAgent.close() _codex_session close-and-clear repair. #55450 is related broader lifecycle work covering additional teardown and transport paths.

@xxiaoxiong

Copy link
Copy Markdown
Author

Closing as duplicate of #66678 (same _codex_session close-and-clear repair). #66678 is the canonical PR. Apologies for the overlap.

@xxiaoxiong xxiaoxiong closed this Jul 18, 2026
Enough1122 pushed a commit to Enough1122/hermes-agent that referenced this pull request Jul 19, 2026
…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

codex comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint duplicate This issue or pull request already exists P3 Low — cosmetic, nice to have provider/openai OpenAI / Codex Responses API sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: session.close leaks the Codex app-server process tree — AIAgent.close never closes _codex_session

2 participants