Skip to content

fix(browser): use process-tree termination for daemon cleanup#29343

Closed
dskwe wants to merge 1 commit into
NousResearch:mainfrom
dskwe:fix/browser-daemon-process-tree
Closed

fix(browser): use process-tree termination for daemon cleanup#29343
dskwe wants to merge 1 commit into
NousResearch:mainfrom
dskwe:fix/browser-daemon-process-tree

Conversation

@dskwe

@dskwe dskwe commented May 20, 2026

Copy link
Copy Markdown
Contributor

Problem

Browser daemon cleanup was leaving orphaned Chromium processes (renderer, GPU, etc.) because we were just calling os.kill(pid, SIGTERM) on the parent. This leaves all the child processes running as orphans, consuming resources over time.

Solution

Switch to ProcessRegistry._terminate_host_pid() which walks the process tree with psutil and terminates children before the parent.

Changes

  • tools/browser_tool.py: Replace os.kill() calls with ProcessRegistry._terminate_host_pid() in _reap_orphaned_browser_sessions() and _cleanup_single_browser_session()
  • tests/tools/test_browser_orphan_reaper.py: Update all 7 related test mocks

How to test

bash scripts/run_tests.sh tests/tools/test_browser_orphan_reaper.py

Or manually verify that browser sessions are cleaned up completely by checking for orphaned Chromium processes after cleanup.

Reuses existing ProcessRegistry._terminate_host_pid() utility which is already well-tested.

@alt-glitch alt-glitch added type/bug Something isn't working tool/browser Browser automation (CDP, Playwright) P2 Medium — degraded but workaround exists labels May 20, 2026
@dskwe dskwe force-pushed the fix/browser-daemon-process-tree branch from 1de07aa to 2c3ca70 Compare May 20, 2026 15:54
@dskwe

dskwe commented May 21, 2026

Copy link
Copy Markdown
Contributor Author

Verified on Linux (Docker):

Simulated a daemon with 3 child processes. After os.kill(parent, SIGTERM) (old code): 3 orphaned children confirmed. New code (_terminate_host_pid) terminates children before parent, fixing the leak.

All tests in test_browser_orphan_reaper.py pass.

Note: CI failures are pre-existing on main branch, not introduced by this PR.

@dskwe dskwe force-pushed the fix/browser-daemon-process-tree branch from 2c3ca70 to 488b95c Compare May 23, 2026 09:01
    os.kill(pid, SIGTERM) only signals the parent, leaving Chromium child
    processes (renderer, GPU, etc.) orphaned.  Reuse the existing
    ProcessRegistry._terminate_host_pid() helper which walks the process
    tree leaf-up via psutil, terminating children before the parent.
@teknium1

Copy link
Copy Markdown
Contributor

Merged via PR #31231 (#31231). Your commit was cherry-picked onto current main with your authorship preserved in the git log (commit 571a0dc). The salvage PR also extended the fix to Windows: the existing _terminate_host_pid helper's Windows branch was effectively a no-op for descendants (os.kill SIGTERM maps to TerminateProcess on a single handle), so the Windows path now shells out to taskkill /PID N /T /F — the documented MS tree-kill primitive, matching the existing gateway.status.terminate_pid(force=True) convention. Thanks for the fix!

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

Labels

P2 Medium — degraded but workaround exists tool/browser Browser automation (CDP, Playwright) type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants