gstack icon indicating copy to clipboard operation
gstack copied to clipboard

v1.40.0.2 fix(browse): Cmd+Q on managed Chromium stops triggering supervisor respawn

Open garrytan opened this issue 1 month ago • 1 comments

Summary

Three `browser.on('disconnected')` handlers in `browse/src/browser-manager.ts` exited with non-zero codes for every disconnect — including user-initiated Cmd+Q. Process supervisors that consume our exit code (gbrowser's `gbd` HealthMonitor) treated this as a crash and respawned the whole stack on exponential backoff. Result: user closes the browser, window pops back 1s later, then 2s, then 4s.

This PR adds `resolveDisconnectCause(browser)` that reads the underlying ChildProcess's `exitCode` + `signalCode` (waiting up to 1s for the exit event if `disconnected` fires first). The three handlers consume it:

  • `launch()` (headless): clean → 0, crash → 1 (was always 1)
  • `launchHeaded()` (headed): clean → 0, crash → 2 (preserved). `onDisconnect()` cleanup still fires in both cases.
  • `handoff()` (mid-session re-launch): clean → 0, crash → 1.

Crash-recovery is preserved: SIGSEGV / SIGKILL / OOM / non-zero exits all still exit non-zero and supervisors restart with backoff. Only the clean Cmd+Q path is new.

Test plan

  • [x] `bun test browse/test/browser-manager-unit.test.ts` — 9 tests pass (7 new for resolver + 2 existing)
  • [x] `bun test browse/test/browser-manager-custom-chromium.test.ts` — still green
  • [ ] Manual: macOS, launch headed Chromium via `bun run dev`, Cmd+Q the window, verify CLI exits 0 (`echo $?`)
  • [ ] Manual: SIGKILL the Chromium PID, verify CLI exits 2 (headed) so supervisor still restarts

Related

  • Companion gbrowser-side PR (this branch): https://github.com/garrytan/gbrowser/pull/23

🤖 Generated with Claude Code

garrytan avatar May 20 '26 14:05 garrytan

Bundled into #1629 as the v1.42.1.1 fix wave, along with PR #1617 and an additional exit-code propagation fix that Codex caught: this PR's launchHeaded() disconnect handler computes exitCode correctly but server.ts:684 hardcoded activeShutdown?.(2), dropping the resolved 0 before it could reach the shutdown pipeline. The bundled PR widens BrowserManager.onDisconnect to accept exitCode, threads it through launchHeaded (this.onDisconnect(exitCode)), and updates the server.ts hookup to (code) => activeShutdown?.(code ?? 2). New regression test pins the full propagation path.

Leaving this PR open until #1629 merges so we have a working fallback. Will close with a final "merged via #1629" once landed.

garrytan avatar May 20 '26 16:05 garrytan

Superseded by v1.42.2.0 (#1629). Closing per the #1642 follow-up note.

garrytan avatar May 26 '26 03:05 garrytan