openai / openai/codex-plugin-cc
Orphaned `codex` process at 100% CPU after Claude Code session ended (PPID=1, main thread spinning in `read()`)
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 33.3k
- Forks
- 2.3k
- PR merge metrics
- No merged PRs in 30d
Description
Summary
Found a stuck codex Rust binary at 98.8% CPU, orphaned (PPID=1), running for 5+ hours after the originating Claude Code session had already exited. This is in the same family as #108 / #163 / #164 (orphaned-process / no-cleanup-on-session-exit), but the leaked process here is the codex CLI binary itself, not app-server-broker.mjs, and crucially it is busy-looping at 100% CPU rather than sitting idle.
Observed process
$ ps aux | grep codex
joseph 94778 98.8 0.0 ... R 3:57PM 38:36.79 .../codex-darwin-arm64/.../codex -s read-only -a untrusted
joseph 94767 0.0 0.1 ... S 3:57PM 0:00.03 node /opt/homebrew/bin/codex -s read-only -a untrusted
$ ps -o pid,ppid,command -p 94767
PID PPID COMMAND
94767 1 node /opt/homebrew/bin/codex -s read-only -a untrusted
PPID=1 (launchd) confirms the original parent died and the process was reparented to init. Started at 3:57 PM, alive at 9:30 PM = ~5.5 h of runtime, accumulated ~39 minutes of CPU time.
Why it burns CPU (not just idle)
sample shows the main thread spinning in a kernel read() syscall:
Call graph:
1417 Thread_xxx DispatchQueue_1: com.apple.main-thread (serial)
+ 1417 start (in dyld) + 6076
+ 1417 ??? (in codex)
+ ...
+ 1415 ??? (in codex)
+ ! 1415 read (in libsystem_kernel.dylib) + 8
1417 Thread_xxx: tokio-runtime-worker
+ ...
+ 1417 _pthread_cond_wait (in libsystem_pthread.dylib)
+ 1417 __psynch_cvwait (in libsystem_kernel.dylib)
(multiple tokio worker threads, all blocked in __psynch_cvwait)
1415 / 1417 samples (~99%) on the main thread are inside read(). All tokio worker threads are correctly parked in pthread_cond_wait. Combined with PPID=1, the most likely interpretation:
When the originating parent process died, the stdin pipe was closed.
read()returns EOF (0). The main loop does not treat EOF as a terminal condition and instead retries the read in a tight loop, producing 100% CPU on a single thread.
This is consistent with the bug class in #191 (fs.readFileSync(0, "utf8") blocking on Windows when stdin handling is wrong) — same root cause shape, different language and a different process. In the Rust binary's case the symptom is busy-loop instead of indefinite block.
Relation to existing issues
- #108 (Broker process not cleaned up on session exit — no idle timeout): same overall problem (process outlives session), but #108 is about
app-server-broker.mjsand the broker runs idle. This report is about the codex Rust binary, and it actively burns a CPU core. - #163 (Test suite leaks broker processes — 158 orphans found): same orphan-cleanup gap, observed in a different code path (test suite tear-down vs. interactive session).
- #164 (Review jobs stuck in 'running' after process death — no dead-PID detection): companion-side blind spot — once the child dies (or busy-loops here), nothing detects it.
- #191 (Stop hook hangs on Windows — stdin blocking read): closest match in shape (blocking/looping
read()on stdin without EOF handling), but in JS hook code, on Windows.
I could not locate the exact plugin code that spawns codex with the literal CLI flags -s read-only -a untrusted. The plugin's lib/app-server.mjs spawns codex with ["app-server"] and passes sandbox / approvalPolicy over the JSON-RPC thread/start params, not as CLI flags. So I'm not 100% certain this orphan was spawned by codex-plugin-cc — it may have been spawned via a different path (e.g., a codex CLI subprocess inside the Rust binary itself, or another tool entirely). I'm filing here because:
- The plugin is the only thing on this machine that drives Codex automated workflows.
- The orphan / no-cleanup pattern matches an active issue cluster on this repo.
- If this is in fact a codex-cli core bug, the maintainers here are best positioned to redirect.
Happy to provide the full sample output, full ps tree, or further reproduction info if it would help.
Environment
- macOS 15.5 (24F74), Apple Silicon
- Node.js v24.6.0
codex-cli0.117.0codex-plugin-ccv1.0.2 (commit8e403f9d)- Claude Code (latest, with codex plugin enabled via
~/.claude/settings.jsonenabledPlugins)
Suggested directions
- Defense in depth: idle / EOF timeout in codex CLI's stdin reader. If
read()on stdin returns EOF, the binary should exit cleanly rather than retry. (Mirrors theidle timeoutsuggestion in #108.) - Plugin-side parent-death detection. When the plugin spawns
codex(in any mode), it could pass an env var or useprctl(PR_SET_PDEATHSIG)(Linux) / a periodic parent-PID check (macOS) so the child self-terminates if its parent dies. - Audit for any CLI-mode
codexinvocation in the plugin with-s read-only -a untrusted. If none exists, this report should be rerouted toopenai/codex(the CLI repo).
Reproducer: I do not have a deterministic reproducer. The orphan was found in Activity Monitor after a normal day of using Claude Code with the plugin enabled. Killing the parent Claude Code process (or letting it crash) is probably the trigger; I will try to reproduce explicitly and follow up.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with lib/app-server.mjs and audit whether the plugin invokes codex with the reported CLI flags or whether that invocation belongs elsewhere. Try to reproduce the parent-session exit while collecting the process tree and stdin behavior, then inspect the relevant EOF handling. Done means the responsible component is identified and the codex process exits cleanly without a CPU-burning orphan, or the issue is redirected to the correct repository.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js, rust
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100