🤖 fix: use stdin.abort() to prevent hangs on SSH commands #504
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.
Problem
Commands like
cat /tmp/results.json | jq '.'would sometimes hang forever over SSH, not respecting timeouts. This was observed over SSH with the bash tool, and it's unclear if it happens on local workspaces.Root Cause
The issue stems from using
WritableStream.close()to close stdin:close()is async and waits for graceful acknowledgment from the remote endclose()promise waits for acknowledgment that may never comeSolution
Use
stdin.abort()instead ofstdin.close()for immediate closure:abort()- Immediate, synchronous force-close. Marks stream as errored, releases locks, doesn't waitclose()- Graceful, async close. Waits for all writes to be acknowledgedApplied selectively:
abort()- commands don't need stdin at allabort()- commands don't read stdinclose()- needs to flush data written to stdinTesting
runtimeExecuteBash- verifies bash commands over SSH workrenameWorkspace- verifies mv operations workruntimeFileEditing- verifies file writes (which use stdin) work correctlyImplementation Details
Changed 4 locations:
src/services/tools/bash.ts- Useabort()to close stdin immediatelysrc/runtime/SSHRuntime.ts(3 places) - Useabort()for mv/rm/stat commandsKept
close()in 1 location:SSHRuntime.writeFile()- Needs graceful close to ensure all data is writtenGenerated with
cmux