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
[browse] Received SIGTERM (ignoring — use /stop or Ctrl+C for intentional shutdown)
…but ~1s after receiving SIGTERM it loses its browser and exits anyway:
[browse] Received SIGTERM (ignoring — use /stop or Ctrl+C for intentional shutdown)
[browse] Tab closed (id=1, remaining=0)
[browse] FATAL unhandled rejection: browser?.process is not a function. (...)
Captured 3× on macOS with daemon stderr redirected to a file (normal spawns are stdio: 'ignore', so this is invisible in the field).
Root cause
chromium.launch() at browse/src/browser-manager.ts:372 does not set the handleSIGINT / handleSIGTERM / handleSIGHUP launch options. Playwright's defaults are true, so Playwright installs its own process-level signal listeners that close the launched browser when the daemon process receives the signal — completely independent of the daemon's own "ignore" handler in server.ts.
Net effect: the app-level SIGTERM handler runs and logs "ignoring", Playwright's handler closes Chromium anyway, the tab closes, browser.disconnected fires, and handleChromiumDisconnect exits the process (currently via the browser?.process() TypeError — #2085 secondary — but it would process.exit() by design even without that bug). The "ignore" is cosmetic.
This matters in practice because killServer() (browse/src/cli.ts:157) leads with SIGTERM: any CLI-initiated restart tears down Chromium through Playwright's hook before the SIGKILL fallback ever fires, so the intended graceful-shutdown/ignore semantics never get a chance to apply. It also means any environment that sprays SIGTERM (session teardown, supervisors) kills the browser even though the daemon deliberately opted out.
Repro
BROWSE_PARENT_PID=0 bun run browse/src/server.ts 2>&1 | tee /tmp/browse.log, wait for healthy, browse goto about:blank.
kill -TERM <daemon pid>.
Log shows "ignoring", then the tab closes and the daemon exits ~1–2s later.
Suggested fix
Pass handleSIGINT: false, handleSIGTERM: false, handleSIGHUP: false to chromium.launch() (and the launchPersistentContext call at browse/src/browser-manager.ts:579), and let the daemon's own signal handlers own the shutdown policy — they already exist and already encode the intended behavior.
Related: the kill-happy CLI path that sends these SIGTERMs during normal QA is filed separately as #2219.
Activity