How Vibium Manages the Browser Process Lifecycle
How Vibium manages the browser process lifecycle: launching Chrome, the process tree it spawns, and how it cleans up so you don't leave zombie processes.
Vibium manages the full browser process lifecycle for you: its single Go binary launches Chrome for Testing through chromedriver, supervises the tree of processes that spawns, and tears everything down cleanly when your script ends. When you call launch(), the binary detects or downloads Chrome, starts it with WebDriver BiDi enabled, and proxies your commands over a local WebSocket. A single session quietly spins up eight to twelve processes — chromedriver, the main Chrome process, and helpers for GPU, network, storage, crash reporting, and one renderer per tab. On quit(), Vibium asks Chrome to close gracefully, then walks the process tree to kill stragglers and sweep up orphans. The point is that you never manage PIDs, match a driver to a browser version, or hunt down leftover Chrome windows. That lifecycle management is a core reason Vibium feels like one tool rather than a stack of moving parts.
What happens when you call launch()?
Calling launch() triggers a chain that ends with a controllable browser. The Go binary detects an existing Chrome for Testing or downloads it on first run, starts chromedriver, and has chromedriver start Chrome with BiDi enabled. It then opens a WebSocket proxy so your client commands reach the browser.
from vibium import browser_sync as browser
# Starts the binary, chromedriver, Chrome, and the BiDi proxy
vibe = browser.launch()
vibe.go("https://example.com")
# Tears the whole tree back down
vibe.quit()From your side it's two lines. Underneath, a small process hierarchy comes to life and is then dismantled. For the full picture of how the binary wears several hats at once, see how Vibium works.
What does the process tree look like?
A live session is a parent-child tree, not a single process. The Go binary sits at the top, chromedriver underneath it, and Chrome for Testing under that — with Chrome spawning its own helpers:
vibium (Go binary)
└── chromedriver
└── Chrome for Testing (main process)
├── chrome_crashpad_handler (crash reporting)
├── GPU helper
├── Network helper
├── Storage helper
├── Renderer helper (one per tab/frame)
└── ...more helpers
That's why a single browser session shows up as eight to twelve processes in your activity monitor. Knowing the shape of the tree explains why cleanup is more involved than "kill one PID."
How does Vibium clean up when a script ends?
Cleanup is a deliberate, multi-step sequence because killing the parent isn't enough. When chromedriver dies, its children — Chrome and all its helpers — get reparented to PID 1 (launchd on macOS, init on Linux) before they can be killed, which would leave orphaned "zombie" processes. Vibium guards against this:
- Graceful quit first. It tells chromedriver to close Chrome cleanly (a best-effort
DELETE /session). - Kill the tree, deepest first. It recursively finds every descendant and kills children before parents, so nothing gets reparented mid-cleanup.
- Sweep for orphans. It looks for any Chrome or chromedriver process whose parent is now PID 1 and kills those too.
- Remove temp dirs. It deletes orphaned Chrome temporary directories so disk clutter doesn't accumulate.
The result: a normal quit() leaves nothing behind.
What happens on Ctrl+C or a crash?
Vibium handles interrupts, with one honest exception. The lifecycle covers the common failure modes:
| Scenario | What happens |
|---|---|
Normal exit (quit()) | The cleanup sequence runs and removes all children |
| Ctrl+C (SIGINT) | A signal handler kills the process tree before exit |
kill -9 on Vibium | Orphans can survive — no cleanup code gets to run |
A hard kill -9 is the one case nothing can intercept, because the binary is terminated instantly. Even then, the orphan sweep in the next session's startup finds and kills the leftovers, so they don't pile up across runs. The Go binary itself is just a process that exits cleanly; the tricky part is always its browser children escaping cleanup.
How do I check for or clear leftover processes?
During heavy local development you can confirm nothing is lingering. To see whether any browser processes are still running:
pgrep -lf 'Chrome for Testing'
pgrep -lf chromedriverTo check whether they're orphaned, inspect their parent PID — an orphan reports PPID = 1:
ps -o pid,ppid,comm -p $(pgrep -f 'Chrome for Testing')In practice you'll rarely need this, because Vibium cleans up on quit() and sweeps on the next launch(). But it's reassuring to know the lifecycle is observable, not magic.
Why does this matter?
Process lifecycle management is the difference between a tool you can run a thousand times in CI and one that slowly fills a machine with stranded Chrome instances. Because Vibium owns the whole tree — start to finish — you don't match driver versions, you don't script your own teardown, and you don't end the day with twenty hidden browsers eating RAM. It's the same single-binary philosophy that removes the ChromeDriver setup step entirely; see installing Vibium and the Vibium vs Selenium comparison for how much manual plumbing this replaces.
Next steps
Frequently asked questions
What processes does Vibium start when you launch a browser?
Vibium's Go binary starts chromedriver, which starts Chrome for Testing, which itself spawns helper processes for the GPU, network, storage, crash reporting, and one renderer per tab. A single session typically runs eight to twelve processes in a parent-child tree.
How does Vibium clean up browser processes when a script ends?
On quit(), Vibium asks chromedriver to close Chrome gracefully, then walks the process tree and kills any remaining descendants, sweeps for orphaned Chrome and chromedriver processes reparented to PID 1, and removes leftover temporary directories so nothing lingers.
Can Vibium leave zombie browser processes behind?
Normal exit and Ctrl+C are handled cleanly. A hard kill -9 can leave orphaned Chrome processes because no cleanup code runs, but Vibium's next session sweeps them up on launch. The Go binary itself exits cleanly and does not leave zombies.
Vibium is created by Jason Huggins. This is an independent tutorial — see the official Vibium site and GitHub repo for canonical docs.
Related guides
WebDriver BiDi vs CDP: What's the Difference?
WebDriver BiDi vs CDP: both are bidirectional protocols, but BiDi is a cross-browser W3C standard while CDP is Chrome-specific and vendor-controlled.
4 min read→Concepts & InternalsEvent-Driven Browser Automation with Vibium
Event-driven browser automation with Vibium uses WebDriver BiDi's pushed events for auto-waiting, console capture, and reliable scripts without sleeps.
4 min read→Concepts & InternalsHow Vibium's Actionability (Auto-Wait) Works
Vibium's actionability auto-wait runs checks (visible, stable, receives events, enabled, editable) server-side in Go before each action — skip sleeps.
4 min read→Concepts & InternalsSelf-Healing Locators in Vibium, Explained
Vibium has no bolt-on self-healing locator engine — it earns resilience via semantic selectors, accessibility-tree finding, pickBest, and auto-wait.
4 min read→