mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-11 15:39:04 +02:00
fix(browse): XProtect launch-kill self-heal — classify, quarantine-clear, bounded reinstall (P0 #2554)
macOS XProtect definition updates can start SIGKILLing the exact Chromium revision the lockfile pins (xprotectd killed revision 1208's headless shell at spawn; the failure surfaced as a generic launch timeout). New browse/src/xprotect-heal.ts heals it, once per process: - Classifier (F9): positive signatures sourced from the #2554 report + Playwright's launch-error format (signal=SIGKILL process-exit lines, and launch timeout WITH a <launched> marker), negative-checked FIRST against missing executable, spawn EACCES/EPERM, Linux sandbox denials, and plain exitCode=1 crashes. darwin-gated. - Heal (F4 one-shot, in-memory flag): clears com.apple.quarantine via `xattr -dr` on chromium* revision dirs in the Playwright cache ONLY — never a GSTACK_CHROMIUM_PATH bundle (probePoisonedChromiumBundle's scope contract, double-gated at the call sites via usesCustomExecutable). - Reinstall (E1/ENG-OV3): `bunx playwright install --force chromium` run FROM THE GSTACK INSTALL ROOT — the root whose node_modules/playwright-core/browsers.json pins the SAME chromium revision our embedded playwright-core expects (a cwd-resolved bunx would fetch latest and heal to the wrong revision). Bounded at 120s with a process-GROUP SIGKILL on timeout; on any heal failure the caller gets the ORIGINAL launch error + manual `bunx playwright install chromium` guidance — the CLI never hangs. - Verification (F9): post-install asserts the REGISTRY-derived executable path exists (the revision dir playwright-core 1.62.1 expects), not merely install exit 0. - Logging (F11): every action emits one structured stderr line ([browse:xprotect-heal] JSON). All three launch sites in browser-manager.ts (headless launch, headed launchPersistentContext, handoff relaunch) route through launchWithXProtectHeal with one post-heal retry. setup's ensure_playwright_browser failure path gains the same quarantine-clear (_clear_playwright_quarantine, Darwin-only, Playwright cache scope) before its Chromium reinstall. Tests: browse/test/xprotect-heal.test.ts — 33 pass (classifier both polarities, one-shot guard incl. failed-heal consumption, custom-executable scope, registry-revision expectation vs playwright-core browsers.json, install-root revision matching, quarantine-clear scope, wrapper retry + guidance surfacing). browser-manager unit/custom-chromium: 36 pass. bridge-chromium-e2e real-launch smoke: 3 pass. setup-windows-fallback ln-invariant: 9 pass. bash -n setup: clean. Fixes #2554. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
2851535f3b
commit
822de7d0c3
@@ -360,6 +360,24 @@ ensure_playwright_browser() {
|
||||
_wait_with_deadline $! 90
|
||||
}
|
||||
|
||||
# P0 #2554: a macOS XProtect definition update can start SIGKILLing the
|
||||
# Chromium revision the lockfile pins, which surfaces here as a failed launch
|
||||
# probe. Clear com.apple.quarantine on the Playwright cache bundles ONLY —
|
||||
# never a GSTACK_CHROMIUM_PATH bundle (that belongs to the wrapper/embedder;
|
||||
# same scope contract as browse's probePoisonedChromiumBundle) — so the
|
||||
# reinstall below produces a launchable browser. Best-effort and macOS-only.
|
||||
_clear_playwright_quarantine() {
|
||||
[ "$(uname -s)" = "Darwin" ] || return 0
|
||||
local cache_root="${PLAYWRIGHT_BROWSERS_PATH:-$HOME/Library/Caches/ms-playwright}"
|
||||
[ -d "$cache_root" ] || return 0
|
||||
local d
|
||||
for d in "$cache_root"/chromium-* "$cache_root"/chromium_headless_shell-*; do
|
||||
[ -d "$d" ] || continue
|
||||
echo " clearing com.apple.quarantine on $(basename "$d") (XProtect self-heal, #2554)" >&2
|
||||
xattr -dr com.apple.quarantine "$d" 2>/dev/null || true
|
||||
done
|
||||
}
|
||||
|
||||
# Ensure a color-emoji font is installed (Linux only).
|
||||
#
|
||||
# Chromium renders emoji code points as .notdef "tofu" (▯) when no color-emoji
|
||||
@@ -629,6 +647,10 @@ fi
|
||||
|
||||
if ! ensure_playwright_browser; then
|
||||
echo "Installing Playwright Chromium..."
|
||||
# XProtect self-heal (#2554): the probe failure may be the OS killing the
|
||||
# cached Chromium, not a missing install. Clear quarantine on the Playwright
|
||||
# cache bundles before reinstalling so the fresh fetch launches clean.
|
||||
_clear_playwright_quarantine
|
||||
_PW_LOCK="${TMPDIR:-/tmp}/gstack-playwright-install.lock"
|
||||
# Stale-lock self-heal: a SIGKILL'd prior setup leaves the lock dir behind
|
||||
# forever (mkdir mutexes have no owner). If the recorded holder PID is dead,
|
||||
|
||||
Reference in New Issue
Block a user