Skip to content

fix(browser): clear stale Chrome singleton lock before launch#1046

Open
RaviTharuma wants to merge 2 commits intoChromeDevTools:mainfrom
RaviTharuma:fix/clear-stale-singleton-lock
Open

fix(browser): clear stale Chrome singleton lock before launch#1046
RaviTharuma wants to merge 2 commits intoChromeDevTools:mainfrom
RaviTharuma:fix/clear-stale-singleton-lock

Conversation

@RaviTharuma
Copy link

@RaviTharuma RaviTharuma commented Feb 26, 2026

Problem

When an MCP client (or its host process) crashes or is killed without cleanly shutting down the browser, Chrome's singleton lock files (SingletonLock, SingletonSocket, SingletonCookie) persist in the user data directory. On the next startup, Chrome refuses to launch because it believes another instance is already running:

The browser is already running for /Users/<user>/.cache/chrome-devtools-mcp/chrome-profile.
Use --isolated to run multiple browser instances.

This is particularly disruptive for MCP clients that manage the browser lifecycle automatically. The only recovery options are manually deleting the lock files or using --isolated (which loses all session state, cookies, and logins). Users who rely on a persistent Chrome profile for authenticated workflows are stuck — they either lose their login state every time, or they have to manually intervene after every crash.

Reproduction

  1. Start chrome-devtools-mcp with a persistent profile (the default)
  2. Kill the parent process (e.g. the MCP client) without giving chrome-devtools-mcp a chance to shut down Chrome
  3. Restart chrome-devtools-mcp → launch fails with the error above

Solution

This PR adds a clearStaleSingletonLock() helper that runs before puppeteer.launch() when a persistent user data directory is in use.

How it works:

  1. Reads the SingletonLock symlink in the user data directory (Chrome writes it as hostname-PID)
  2. Extracts the PID and checks whether the process is still alive via process.kill(pid, 0)
  3. If the process is dead → removes SingletonLock, SingletonSocket, and SingletonCookie so Chrome can start cleanly
  4. If the process is alive → leaves everything untouched; Chrome's own conflict detection handles it normally

This is a safe, minimal change:

  • Only touches lock files when the owning process is confirmed dead
  • No new dependencies
  • No behavioral change when Chrome is running normally
  • Existing --isolated behavior is unaffected

Test plan

  • tsc --noEmit passes
  • Stale lock (dead PID) → lock files removed, Chrome can start
  • Live lock (own PID) → lock files preserved, no interference
  • No lock file present → no-op, no errors
  • Complex hostname format with multiple dashes (e.g. macbook-pro-16---m1-max.home-85428) → PID correctly extracted
  • Garbage lock content (no parseable PID) → left alone, no errors

When an MCP client (or the host process) crashes or is killed without
cleanly shutting down the browser, Chrome's singleton lock files
(SingletonLock, SingletonSocket, SingletonCookie) persist in the user
data directory. On the next startup Chrome refuses to launch because it
believes another instance is already running, producing the error:

  "The browser is already running for <userDataDir>."

This is particularly disruptive for MCP clients that manage the browser
lifecycle automatically — users have to manually find and delete the
lock files or restart their machine to recover.

This commit adds a `clearStaleSingletonLock()` helper that runs before
`puppeteer.launch()` when a persistent user data directory is in use.
It reads the PID encoded in the SingletonLock symlink (format:
`hostname-PID`), checks whether that process is still alive via
`process.kill(pid, 0)`, and removes the lock files only when the
process no longer exists. If the process is still running the lock is
left untouched and Chrome's own conflict detection handles it normally.
@google-cla
Copy link

google-cla bot commented Feb 26, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@RaviTharuma
Copy link
Author

I have signed the CLA.

@Lightning00Blade Lightning00Blade self-requested a review February 26, 2026 08:16
@OrKoN
Copy link
Collaborator

OrKoN commented Mar 2, 2026

I believe Chrome is managing the lock files and we should not be clearing it for Chrome. I believe Chrome should already detect if the process is running. Do you have a test case or a screencast of this happening? Perhaps the fix needs to be done on the Chrome side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants