mirror of https://github.com/garrytan/gstack.git
A headed session against a beacon-heavy page (analytics/extension load) could tip
the single-threaded daemon into a self-inflicted crash-loop: a brief HTTP stall
was read as a crash, the restart didn't clear the dead Chromium's SingletonLock,
the relaunch failed, and the session silently came back headless. Four fixes:
1. Busy-vs-dead (sendCommand): on a connection error, if the process is alive give
/health a bounded probe (3x/250ms) and just retry the command — never kill+restart
a live-but-busy server. A 30s timeout now reports 'busy, not restarting' when the
process is alive instead of exiting into a kill cycle.
2. Profile-lock cleanup on (re)start: startServer reaps the orphaned Chromium holding
the SingletonLock and clears Singleton{Lock,Socket,Cookie} before relaunch, so the
auto-restart path gets the same clean profile the manual connect preamble did.
3. Headed persistence: the restart env reapplies BROWSE_HEADED from this invocation OR
the persisted server state (mode==='headed'), so a restart from a plain command
never downgrades a headed window to invisible headless. Extracted to buildRestartEnv.
4. Force-clean disconnect reaps the Chromium child tree (via the SingletonLock PID) so
the next connect starts clean instead of fighting an orphan.
Plus macOS window surfacing: connect + focus raise 'Google Chrome for Testing' to the
active Space (best-effort osascript) with a Mission Control hint — the first thing
users read as 'I can't see the browser'.
Shared lock helpers (chromiumProfileDir / cleanChromiumProfileLocks / killOrphanChromium)
dedupe the connect, disconnect, and restart paths. browse/test/restart-env.test.ts pins
the headed-persistence decision; the full crash-loop repro is an E2E (periodic).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|---|---|---|
| .. | ||
| bin | ||
| scripts | ||
| src | ||
| test | ||
| PLAN-snapshot-dropdown-interactive.md | ||
| SKILL.md | ||
| SKILL.md.tmpl | ||