Process substitution causes indefinite hang - orphaned grandchild processes not terminated
What version of Codex is running?
codex-cli 0.66.0
What subscription do you have?
PRO
Which model were you using?
gpt-5.1-codex-max
What platform is your computer?
Linux 6.8.0-87-generic x86_64 x86_64
What issue are you seeing?
When Codex executes shell commands containing bash process substitution
(e.g., exec > >(tee -a file.log) 2>&1 && command), grandchild processes
like tee remain orphaned after the main command completes successfully.
Symptoms:
- Codex hangs indefinitely waiting for command completion
raw_output.jsonlshows:"exit_code": null, "status": "in_progress"- Orphaned processes visible in
ps:tee,timeout,pythonin sleeping state (S) - The actual command completes successfully (tests pass), but Codex never receives EOF
Example from logs:
``json``
{
"type": "item.started",
"item": {
"type": "command_execution",
"command": "exec > >(tee -a /tmp/test.log) 2>&1 && python -m pytest tests/ -q",
"exit_code": null,
"status": "in_progress"
}
}
Process state after hang:
| PID | PPID | S | ELAPSED | CMD |
|--------|--------|---|---------|------------------------------|
| 135079 | 134817 | S | 01:06 | timeout 10m python -m pytest ... |
| 135084 | 135079 | S | 01:06 | tee -a /tmp/pytest.log |
| 135085 | 135079 | S | 01:06 | python -m pytest ... |
What steps can reproduce the bug?
Minimal reproduction
- Run Codex with a command using process substitution:
``bash``
codex exec --dangerously-bypass-approvals-and-sandbox \
"exec > >(tee -a /tmp/test.log) 2>&1 && echo 'test passed'"
- Wait ~5-10 seconds, then check for orphaned processes:
``bash``
pgrep -af 'tee.*test.log'
- Observe that
teeprocess remains running even thoughechocompleted.
## Full reproduction script
```bash
#!/bin/bash
# Save as /tmp/codex_hang_repro.sh
set -euo pipefail
# Record PIDs before test
BEFORE=$(pgrep -f 'tee.*codex_test' 2>/dev/null || true)
# Run codex with process substitution
timeout 30s codex exec --dangerously-bypass-approvals-and-sandbox \
"exec > >(tee -a /tmp/codex_test.log) 2>&1 && echo test" &
CPID=$!
sleep 10
# Check for orphaned processes
AFTER=$(pgrep -f 'tee.*codex_test' 2>/dev/null || true)
if [[ -n "$AFTER" ]]; then
echo "BUG REPRODUCED: Orphaned tee process found"
ps -p $AFTER -o pid,ppid,state,etime,cmd
kill -9 $AFTER 2>/dev/null
exit 1
fi
echo "No hang detected"
```
## Environment
- Shell: bash
- Note: Direct command execution works fine (~0.1s)
- Note: Issue only occurs when Codex spawns the shell
What is the expected behavior?
When the main command completes (e.g., echo or pytest), all child processes
including those created by process substitution (tee) should be terminated,
and Codex should receive the exit code and return control to the user.
Expected:
- Command completes in <1 second
- All child processes terminated
exit_code: 0reported- No orphaned processes
Additional information
_No response_
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗