-
Notifications
You must be signed in to change notification settings - Fork 244
Description
Problem
When the daemon process dies unexpectedly (crash, forced kill, or certain session-stop timing issues), the Chrome browser process it spawned becomes orphaned but continues running. This creates a cascading failure:
- Orphaned Chrome holds the
userDataDirlock —launchPersistentContextprevents reusing the sameuserDataDirwhile another Chrome instance is using it - New session can't reuse previous cookies — starting a new session either errors out ("Browser is already in use for ...") or requires a fresh
userDataDir - Authentication state is lost — for SAML/SSO-protected sites, the session cookie (
_fi_sesson GitHub Enterprise, for example) is a session cookie (expires=0), meaning it's destroyed when the Chrome process terminates - Process accumulation — repeating this cycle accumulates orphaned Chrome processes (I had 47 at one point)
Root cause analysis
The daemon spawns Chrome with detached: true + child.unref() (program.js:201-214), which correctly decouples the daemon from its parent. However, when the daemon exits (via session-stop → gracefullyProcessExitDoNotHang), the Chrome process it launched is not guaranteed to terminate:
Context.disposeAll()callsbrowserContext.close(), which should close Chrome- But if this takes longer than the 15-second watchdog timeout (watchdog.js:32),
process.exit(0)is called while Chrome is still running - The orphaned Chrome process has no parent to send SIGTERM to it
Evidence
$ playwright-cli session-list
(no sessions)
$ playwright-cli open https://example.com
Error: Browser is already in use for /Users/me/.playwright-cli/ghe-profile
$ ps aux | grep ghe-profile | head -1
user 93516 ... /Applications/Google Chrome.app/.../Google Chrome --user-data-dir=/Users/me/.playwright-cli/ghe-profile --remote-debugging-port=55665 ...
$ ps -o ppid= -p 93516
→ Parent process gone (orphan!)
Proposed solution
1. Kill orphaned Chrome on session-stop (critical)
Before or after sending the "stop" message to the daemon, detect and kill Chrome processes associated with the session's userDataDir. This could use:
- The CDP port recorded during launch to send
Browser.close()via CDP - Or
lsof/ process scanning to find Chrome processes using the specificuserDataDir
2. Reconnect to orphaned Chrome via CDP (nice-to-have)
If a Chrome process is found with a known --remote-debugging-port, attempt CDP reconnection instead of launching a new instance. This would preserve the existing authentication state.
3. Cookie persistence across session restarts (nice-to-have)
Add cookies export <file> / cookies import <file> commands (similar to browser-use CLI) to save/restore authentication state. This would help with SAML/SSO sites where session cookies are lost on browser restart.
Environment
- OS: macOS (Darwin 25.3.0)
- playwright-cli: 0.0.61 (@playwright/cli)
- Browser: Google Chrome (system Chrome via
--profile)
Related
- unable to open two session at once #293 — "unable to open two session at once" (same underlying
launchPersistentContextsingle-instance constraint)