get2knowio / get2knowio/airframe

Investigate openai-codex-sdk subprocess transport leak on failed runs

Open
#9 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
0
Forks
0
PR merge metrics
No merged PRs in 30d

Description

## Summary

When ``CodexRuntime`` raises any exception during ``execute()`` (e.g.
``RuntimeModelNotFoundError`` on a wrong model, ``RuntimeAuthError``,
schema validation failure), the user sees the correct exit code and
error message — but Python prints trailing noise from a subprocess
transport that wasn't cleaned up before ``asyncio.run()`` closed the
loop:

\`\`\`
Exception ignored in:
RuntimeError: Event loop is closed
Task was destroyed but it is pending!
\`\`\`

## Where the bug lives

Inside ``openai-codex-sdk`` — specifically the ``Thread.run()`` failure
path. The SDK spawns a ``codex exec`` subprocess (tracked by a Python
``BaseSubprocessTransport``) but doesn't await its shutdown when the
turn raises. Python's garbage collector then runs the transport's
``__del__`` after the asyncio loop is closed.

Airframe's ``CodexAgentSession.close()`` already does the right thing on
its side (``controller.abort()`` + reference drop), but the transport
lives inside the SDK's ``Thread`` object — out of reach.

## Why this isn't blocking

- Exit code is correct (1 on failure).
- Structured error + hint print before the noise.
- Only happens on failed runs (successful round-trips are clean).
- Nothing leaks across the Python process boundary; the OS reaps the
subprocess when the script exits.

## What to do

1. Reproduce against ``openai-codex-sdk`` directly (minimal repro
outside airframe).
2. File upstream issue with the repro.
3. Optionally add a workaround in ``airframe.adapters.codex`` if upstream
doesn't move — e.g. weakly-track spawned transports and call
``transport.close()`` explicitly in ``runtime.close()``. Weigh
workaround complexity against living with the warning.

## Reproduction

Any failed ``CodexRuntime`` call shows it. Easiest path:

\`\`\`bash
unset AIRFRAME_PROBE_MODEL_CODEX OPENAI_API_KEY
# requires ChatGPT-account auth via `codex login`
uv run python examples/probe_codex.py
\`\`\`

The probe will raise ``RuntimeModelNotFoundError`` (since ``gpt-5-codex``
isn't served under ChatGPT-account auth), and you'll see the trailing
``Event loop is closed`` exception ignored by the GC.

Contributor guide

Open the contributing guide

Research direction

Run the minimal reproduction in examples/probe_codex.py, then reproduce the failure directly against openai-codex-sdk. Inspect the Thread.run() failure path and Airframe's CodexAgentSession.close() or runtime.close() behavior. Done means an upstream issue is filed with the reproduction, or a justified workaround is added in airframe.adapters.codex.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.