macOS sandbox exec hangs after output (job-control SIGTTIN when setpgid + inherited stdio)
Summary
On macOS, Codex sandboxed exec (including the transparent exec path used by the agent, not just the codex sandbox CLI) can hang after commands like elixir -v. The command prints output then never exits. This blocks running Mix/Elixir commands in Codex.
Reproduction
codex sandbox macos --full-auto /bin/sh -c 'elixir -v; echo DONE'
# prints Elixir version, then hangs (no DONE)
codex sandbox macos --full-auto /bin/sh -c 'erl -noshell -eval "io:format(\"ok~n\"), halt()."; echo DONE'
# prints ok, then hangs
Environment
- macOS (Apple Silicon, arm64)
- Elixir 1.19.4 / Erlang OTP 28
- Codex commit: 82fcc087b5ff949820aec0c48d3ea2194928f2e3
Root Cause
Codex’s spawn path calls setpgid(0,0) unconditionally on Unix. When stdio is inherited (i.e., connected to the controlling TTY), the child ends up in a background process group. If it reads from the TTY, the OS sends SIGTTIN and stops the process. This looks like a hang after output.
Proposed Fix
Only call setpgid when stdio is redirected (piped output for shell tool). When stdio is inherited, keep the child in the parent’s process group. This avoids job-control stops while preserving killpg cleanup for piped/redirected commands.
Status
I have a local change implementing the above and can open a PR shortly. The fix is in core/src/spawn.rs.
---
Filed by @seeekr with assistance from Codex AI; we’re working together and will provide a PR soon.