fix(cli): start sandbox exec without waiting for piped stdin EOF - #4006
Merged
Merged
Conversation
With a non-terminal stdin, sandbox exec read stdin to EOF before it sent the exec request. A pipe that never closes (CI runners, supervisors, agent harnesses) blocked the CLI forever in read(2) without the gateway ever seeing the request, and a slow producer delayed the command until EOF. Collect piped stdin on a detached reader thread for at most 200 ms. Input that reaches EOF within that window still travels in the single request that older gateways need. If the pipe is still open, start the command through the streaming RPC and forward the collected prefix plus the rest of stdin as it arrives, closing remote stdin at EOF. The 4 MiB cap covers the prefix and the streamed remainder together. Closes NVIDIA#3993 Signed-off-by: Federico Kamelhar <federico.kamelhar@oracle.com>
fede-kamel
requested review from
a team,
derekwaynecarr,
mrunalp and
sjenning
as code owners
September 30, 2026 21:47
Contributor
Author
|
I have read the DCO document and I hereby sign the DCO. |
|
Label |
Collaborator
|
/ok to test d250bca |
johntmyers
reviewed
Oct 1, 2026
johntmyers
left a comment
Collaborator
There was a problem hiding this comment.
gator-agent
PR Review Status
This focused fix is project-valid against #3993, the user-facing documentation is updated, and the independent initial review found no blocking issues.
Blocking findings:
- No blocking findings remain
Carried findings:
- None
Non-blocking suggestions:
- None
Gator metadata
- Validation: Fixes the reproducible linked CLI hang in a concentrated subsystem.
- Docs: Fern sandbox execution behavior is updated; navigation is unchanged because no page was added or moved.
- Checks: Current-head required checks are awaiting the copy-pr mirror and workflow dispatch.
- E2E:
test:e2eapplied; authorized/ok to testposted for the current head; Branch E2E is not yet confirmed queued. - Head SHA:
d250bca506c906e0bca9c32e29ca27d255bebf33 - Base SHA:
912a077bd641272016fb8b2fd58209f6c7c6f194 - Merge base SHA:
912a077bd641272016fb8b2fd58209f6c7c6f194 - Patch ID:
e962ee5e74ba782674e05bccde01348171cfa49a - Gator payload:
9 - Review mode:
initial - Previous reviewed SHA: none
- Review budget exhausted: no
- Maintainer decision required: no
- Next state:
gator:in-review
run the worker command inside the running sandbox</dev/null avoids the stdin-EOF hang (#3993) on 0.1.2openshell sandbox exec -n "$NAME" -- </dev/null |
johntmyers
approved these changes
Oct 1, 2026
johntmyers
approved these changes
Oct 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
openshell sandbox execread piped stdin to EOF before it sent the exec request. Under any parent that keeps stdin open (CI runners, supervisors, agent harnesses) the CLI hung forever without the gateway ever seeing the request, and a slow producer delayed the command until EOF. The CLI now waits at most 200 ms for piped stdin to end; small pipes keep the single-request path, and an open pipe starts the command through the streaming RPC with stdin forwarded as it arrives.Related Issue
Closes #3993.
Changes
crates/openshell-cli/src/run.rs:spawn_piped_stdin_readerreads stdin on a detached OS thread and hands chunks over a channel;collect_piped_stdingathers them until EOF orEXEC_STDIN_UNARY_GRACE(200 ms).Completeinput goes into the unary request as before.Openinput routes tosandbox_exec_streaming_grpc, which gains astdin_restreceiver and forwards the collected prefix plus the remainder, closing remote stdin at EOF. The 4 MiB cap applies to prefix plus remainder; the error text is unchanged. The terminal path is untouched.docs/how-it-works/sandboxes/overview.mdx: document the grace period and the</dev/nullidiom for commands that need no input.Testing
run::tests::piped_stdin_*): a pipe that closes immediately is sent in one request; a pipe that stays open returns after the grace period with the prefix collected so far and keeps delivering later bytes until EOF; input over the limit is rejected with thesandbox uploadhint.cargo test -p openshell-cli(all suites),cargo clippy -p openshell-cli --all-targets -D warnings,cargo fmt --all --check.sleep 300 | openshell sandbox exec -n sb -- truehung until killed and produced noExecSandboxRPC in the gateway log;</dev/nullreturned in 0.1 s; a pipe closing after 5 s started the command 5 s late. These are the reproduction steps in sandbox exec reads piped stdin to EOF before starting the command; hangs forever when stdin is an open pipe #3993.Checklist