fix(codex): suppress stdout/stderr stream errors in sandbox subprocesses#101777
fix(codex): suppress stdout/stderr stream errors in sandbox subprocesses#101777sunlit-deng wants to merge 9 commits into
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 26, 2026, 5:23 AM ET / 09:23 UTC. ClawSweeper reviewWhat this changesThe PR prevents stdout or stderr errors from Codex sandbox helper processes from crashing the exec-server bridge, while keeping streaming HTTP execution finalization owned by child close. Merge readinessThis PR remains necessary: current Priority: P1 Review scores
Verification
How this fits togetherThe bundled Codex plugin runs sandbox helper processes for process-RPC and streaming HTTP requests. Their stdout/stderr data drives WebSocket and HTTP responses, while the helper's close event releases the backend execution lease. flowchart LR
Request[Sandbox request] --> Helper[Sandbox helper process]
Helper --> Streams[stdout and stderr streams]
Streams --> Rpc[Process-RPC bridge]
Streams --> Http[Streaming HTTP response]
Streams --> Error[Stream error handling]
Helper --> Close[Child close]
Close --> Finalize[Execution lease finalization]
Before merge
Agent review detailsSecurityNone. PR surfaceSource +63, Tests +291. Total +354 across 5 files. View PR surface stats
Review metricsNone. Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Rebase this focused reliability fix onto current Do we have a high-confidence way to reproduce the issue? Yes, at source level: emitting an Is this the best way to solve the issue? Yes, subject to current-head refresh: handling errors at each subprocess owner and retaining child-close ownership of finalization is narrower than adding a bridge-wide fallback. The helper extraction also lets streaming HTTP distinguish request settlement from execution-lease release. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against afb347c7f94f. LabelsLabel justifications:
EvidenceWhat I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (53 earlier review cycles; latest 8 shown)
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
fa2b97f to
af1cb33
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@clawsweeper re-review |
af1cb33 to
e5324ca
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
2fefe95 to
c4252b6
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
c4252b6 to
233a415
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
233a415 to
28a0a3e
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
…r stream errors Route stdout/stderr error events through fail() inside readStreamingSandboxHttpResponse so that a pre-header stream error settles the request exactly once instead of hanging indefinitely when the child process stays alive. The outer no-op error listeners on the same streams (installed before calling readStreamingSandboxHttpResponse) prevent the EventEmitter from throwing before the settlement listener fires.
Separate stream-error request settlement from backend finalization so the exec-server lease stays held while the helper process is still alive. The close handler now owns finalizeExec for both child errors and stream errors, preserving the close-authoritative lifecycle contract.
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
What Problem This Solves
Fixes an issue where stdout or stderr pipe errors from Codex sandbox subprocesses could become unhandled Node stream errors and crash the exec-server WebSocket bridge.
Why This Change Was Made
Both sandbox subprocess owners now handle output-stream errors immediately. The process-RPC path keeps child close authoritative for exit/closed notifications, while the streaming HTTP path settles the response, terminates the helper, and defers backend finalization until child close.
User Impact
Codex sandbox process and streaming HTTP work no longer take down the bridge when an output pipe fails, and execution leases are still finalized exactly once after the child exits.
Evidence
startProcess()path; the WebSocket remained open, follow-upreadProcess()succeeded, andprocess/closedarrived after child close.EPIPEand exit code 1../node_modules/.bin/tsx proof-live.tsused the production response reader with a real child process and loopback WebSocket. The request settled on stream error, the socket stayed open,finalizeExecremained at zero before close, and ran exactly once after close.openai/codex@61a44880a85d:codex-rs/exec-server/src/process.rsdistinguishesExited(process exit) fromClosed(all output streams ended), whilecodex-rs/exec-server/src/local_process.rsemitsClosedonly after an exit code exists and the open-stream count reaches zero. The exec-server README documents the sameprocess/exitedthenprocess/closedlifecycle. This confirms the branch's close-authoritativefinalizeExecordering: stream failure settles the request and terminates the helper, while backend finalization waits for child close.openclaw/openclaw@bfd6f2efdc54.node scripts/run-vitest.mjs extensions/codex/src/app-server/sandbox-exec-server.pipe-survival.test.ts extensions/codex/src/app-server/sandbox-exec-server.http.test.ts extensions/codex/src/app-server/sandbox-exec-server.lifecycle.test.ts extensions/codex/src/app-server/sandbox-exec-server.test.ts.proof-live.ts
AI-assisted: built with Codex