fix(desktop): prevent WSL backend exiting with code 0 by keeping stdi…#3613
fix(desktop): prevent WSL backend exiting with code 0 by keeping stdi…#3613jibin7jose wants to merge 3 commits into
Conversation
…n open Fixes pingdotgg#3611 by appending Stream.never to the bootstrap stream so the Windows-side pipe does not close before the backend process completes reading it.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Needs human review 1 blocking correctness issue found. This PR introduces new WSL backend failure tracking and fallback logic, with multiple unresolved review comments identifying potential bugs: the You can customize Macroscope's approvability policy. Learn more. |
Tests using fd3 delivery were hanging because the stream never terminated. Only stdin delivery (WSL) needs the stream kept open.
…gg#3611) Consolidates fixes from PRs pingdotgg#3613, pingdotgg#3621, and pingdotgg#3623 to address both root causes and add a fail-safe: 1. DesktopWslEnvironment: Parse the Node version in the WSL node-pty probe and validate it against options.nodeEngineRange. Preflight now fails cleanly with an actionable error if the distro's default Node is incompatible. 2. DesktopBackendManager: Track neverReadyAttempt to cap consecutive post-spawn exits on stdin delivery. Prevents the desktop from permanently getting stuck restarting if the WSL backend consistently fails before readiness. 3. bootstrap: Clean up the readline interface on all event paths to prevent leaks when stdin stays open, and register the error listener on the readline interface to safely catch early stream errors.
340fb76 to
215bd10
Compare
Dismissing prior approval to re-evaluate 215bd10
There was a problem hiding this comment.
🟡 Medium
stop() and a fresh manual start() never reset neverReadyAttempt, so a WSL backend that was stopped after a few pre-readiness exits inherits the old failure streak on the next start cycle. The new run can then trigger onPreflightFailed after a single additional exit, falling back to Windows even though the user initiated a fresh retry. Consider resetting neverReadyAttempt to 0 in both stop() and at the top of start() (alongside the existing preflightFailureAttempt reset).
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/desktop/src/backend/DesktopBackendManager.ts around line 807:
`stop()` and a fresh manual `start()` never reset `neverReadyAttempt`, so a WSL backend that was stopped after a few pre-readiness exits inherits the old failure streak on the next start cycle. The new run can then trigger `onPreflightFailed` after a single additional exit, falling back to Windows even though the user initiated a fresh retry. Consider resetting `neverReadyAttempt` to `0` in both `stop()` and at the top of `start()` (alongside the existing `preflightFailureAttempt` reset).
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 215bd10. Configure here.
| ) { | ||
| yield* mutex.withPermits(1)( | ||
| Effect.gen(function* () { | ||
| const { isCurrentRun, nextState, pid } = yield* Ref.modify( |
There was a problem hiding this comment.
Never-ready counter not reset
Medium Severity
The neverReadyAttempt counter for WSL backends isn't reset when the backend stops and restarts, unlike preflightFailureAttempt. This allows a partial failure count to persist across sessions, causing the WSL fallback mechanism to trigger prematurely after fewer new failures than intended.
Reviewed by Cursor Bugbot for commit 215bd10. Configure here.
| const bootstrapStream = Stream.make(`${bootstrapJson}\n`).pipe( | ||
| options.bootstrapDelivery === "stdin" ? Stream.concat(Stream.never) : (s) => s, | ||
| Stream.encodeText, | ||
| ); |
There was a problem hiding this comment.
Readiness flag races process exit
Medium Severity
neverReadyAttempt uses latest.ready in finalizeRun, but readiness is set in a forked waitForHttpReady fiber while runBackendProcess awaits handle.exitCode on the main path. If the child exits right after the HTTP probe succeeds but before onReady updates state, a run that was actually ready can be counted as a never-ready failure.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 215bd10. Configure here.


…n open
Fixes #3611 by appending Stream.never to the bootstrap stream so the Windows-side pipe does not close before the backend process completes reading it.
What Changed
Why
UI Changes
Checklist
Note
Medium Risk
Changes affect WSL backend spawn/restart and stdin bootstrap paths on Windows; behavior is more defensive but alters when restarts stop and how failures surface.
Overview
Fixes WSL backends exiting with code 0 when bootstrap is delivered over stdin by keeping the parent pipe open: the bootstrap stream now appends
Stream.neverafter the JSON line so the child does not see EOF while the server is still starting (#3611).Desktop backend manager adds a
neverReadyAttemptcounter for stdin-delivery runs that exit before HTTP readiness. After five consecutive such exits it callsonPreflightFailed(same cap as fatal preflight) so the app can fall back to Windows instead of restarting forever; reaching readiness resets the counter. Windows fd3 delivery is unchanged.WSL preflight now prints and parses
nodeVersion:from the node-pty probe and rejects distros whose default Node does not satisfy the serverenginesrange, with a clear fatal message instead of a silent exit.Server bootstrap readline handling registers errors on the readline
inputinterface (not only the raw stream), runscleanupon error/line/close, and removes listeners frominputso early stdin errors are handled reliably across the WSL pipe.Reviewed by Cursor Bugbot for commit 215bd10. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Prevent WSL backend from exiting with code 0 by keeping stdin open
Stream.neverafter writing the bootstrap envelope inDesktopBackendManager.ts, preventing the child process from exiting cleanly when stdin closes.MAX_PREFLIGHT_FAILURE_ATTEMPTS, callsonPreflightFailedand either stops or restarts the backend.DesktopWslEnvironment.tsand validates it against anodeEngineRangeif provided, failing fast with a fatal error when the version is missing or incompatible.bootstrap.tsto attach to the readline interface rather than the raw stream, ensuring cleanup runs on all error paths.📊 Macroscope summarized 215bd10. 3 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted
🗂️ Filtered Issues
No issues evaluated.