From 5bd05c9e0f8d4a203d58213605eefa06985da437 Mon Sep 17 00:00:00 2001 From: Garry Tan Date: Sun, 5 Apr 2026 22:54:33 -0700 Subject: [PATCH] fix(browse): terminate orphan server when parent process exits (#808) Community PR #808 by @mmporong. Passes BROWSE_PARENT_PID to the spawned server process. The server polls every 15s with signal 0 and calls shutdown() if the parent is gone. Prevents orphaned chrome-headless-shell processes when Claude Code sessions exit abnormally. Co-Authored-By: mmporong Co-Authored-By: Claude Opus 4.6 (1M context) --- browse/src/cli.ts | 4 ++-- browse/src/server.ts | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/browse/src/cli.ts b/browse/src/cli.ts index 10c2646d..96051847 100644 --- a/browse/src/cli.ts +++ b/browse/src/cli.ts @@ -232,7 +232,7 @@ async function startServer(extraEnv?: Record): Promise): Promise { } }, 60_000); +// ─── Parent-Process Watchdog ──────────────────────────────────────── +// When the spawning CLI process (e.g. a Claude Code session) exits, this +// server can become an orphan — keeping chrome-headless-shell alive and +// causing console-window flicker on Windows. Poll the parent PID every 15s +// and self-terminate if it is gone. +const BROWSE_PARENT_PID = parseInt(process.env.BROWSE_PARENT_PID || '0', 10); +if (BROWSE_PARENT_PID > 0) { + setInterval(() => { + try { + process.kill(BROWSE_PARENT_PID, 0); // signal 0 = existence check only, no signal sent + } catch { + console.log(`[browse] Parent process ${BROWSE_PARENT_PID} exited, shutting down`); + shutdown(); + } + }, 15_000); +} + // ─── Command Sets (from commands.ts — single source of truth) ─── import { READ_COMMANDS, WRITE_COMMANDS, META_COMMANDS } from './commands'; export { READ_COMMANDS, WRITE_COMMANDS, META_COMMANDS };