You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
🤖 fix: correct-by-construction process cleanup to prevent SSH hangs
## Problem
Commands like `grep -RIn ... | head -n 200` would hang over SSH runtime,
not respecting timeouts. Previous fix (PR #504) using stdin.abort() addressed
a symptom but not the root cause.
## Root Cause
bash.ts waited for THREE conditions before finalizing:
- exitCode !== null
- stdoutEnded (stream 'close' event)
- stderrEnded (stream 'close' event)
Over SSH with ControlMaster multiplexing, stream 'close' events don't
propagate reliably. The 50ms grace period fallback was insufficient, allowing
hangs on commands that take longer or during high SSH latency.
## Solution
**Single source of truth: process exit triggers all cleanup**
Created DisposableProcess wrapper that:
1. Registers cleanup callbacks (stream destruction, etc.)
2. Auto-executes cleanup when process exits
3. Makes it IMPOSSIBLE to wait for stream events that never arrive
Key changes:
- SSHRuntime.exec(): Use DisposableProcess, cancel streams on exit
- LocalRuntime.exec(): Same pattern for consistency
- bash.ts: Simplified from complex multi-condition wait to simple `await exitCode`
## Benefits
- ✅ Fixes the hang completely
- ✅ Simpler: Removed ~130 LoC of complex finalization logic
- ✅ Faster: No 50ms grace period on every command
- ✅ Correct by construction: Process lifetime bounds all resources
## Impact
**Invariant**: When exitCode resolves, streams are already destroyed.
**Proof**: DisposableProcess registers cleanup on process 'close' event,
which fires before exitCode promise resolves. Therefore: exitCode resolved ⟹
streams destroyed. No race conditions possible.
## Testing
- All 955 unit tests pass
- Added regression test for grep|head pattern
- bash.ts tests validate no hangs
- LocalRuntime/SSHRuntime tests pass
---
_Generated with `cmux`_
0 commit comments