Skip to content

File descriptor leak due to unclosed WebSocket connections #3705

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from

Conversation

felipehertzer
Copy link

@felipehertzer felipehertzer commented Apr 28, 2025

Description

SeleniumBase was leaving WebSocket connections open, causing file descriptors and socket connections to accumulate over time. This results in resource exhaustion and instability when running tests that repeatedly open and close browser instances. #3679


Affected Components

  • browser_launcher.py
  • browser.py
  • sb_manager.py
  • connection.py

Steps to Reproduce

  1. Write a simple test that opens and closes a SeleniumBase browser instance multiple times, for example:
    for i in range(5):
        with SB(uc=True) as sb:
            sb.activate_cdp_mode("https://example.com")
  2. Monitor your process’s file descriptor count (e.g., lsof, psutil.Process().open_files() + .connections()).
  3. Observe that the count increases with each iteration—even though the browser context has exited.

Expected Behaviour

  • All WebSocket connections opened by SeleniumBase should be closed when the browser context is exited.
  • File descriptor count should return to baseline after each browser instance is closed.

Actual Behaviour

  • The WebSocket connections created for DevTools (both browser and page channels) remain open.
  • File descriptor count and open TCP connections accumulate with each browser instantiation.

Root Cause

  1. browser_launcher never explicitly closes the DevTools requests made when initializing a new driver.
  2. _handle_target_update asynchronously opens connections to handle iframes and background services without ensuring they are closed when the handler scope ends.
  3. sb_manager does not iterate through all active Connection objects to close their page requests and associated event loops.

@felipehertzer felipehertzer changed the title File descriptor leak due to unclosed WebSocket connections in SeleniumBase File descriptor leak due to unclosed WebSocket connections Apr 28, 2025
@mdmintz
Copy link
Member

mdmintz commented Apr 28, 2025

Those changes cause a regression in scripts that open new tabs. Eg:

from seleniumbase import SB

with SB(uc=True) as sb:
    sb.activate_cdp_mode()
    sb.open("data:text/html,<h1>Page A</h1>")
    sb.assert_text("Page A")
    sb.open_new_tab()
    sb.open("data:text/html,<h1>Page B</h1>")
    sb.assert_text("Page B")
    sb.switch_to_tab(0)
    sb.assert_text("Page A")
    sb.assert_text_not_visible("Page B")
    sb.switch_to_tab(1)
    sb.assert_text("Page B")
    sb.assert_text_not_visible("Page A")
RuntimeError: coroutine raised StopIteration
ERROR:asyncio:Task was destroyed but it is pending!

Needs some work.

@mdmintz
Copy link
Member

mdmintz commented Apr 28, 2025

See #3679 (reply in thread) and #3679 (reply in thread).
I added a few things from here that didn't cause issues into 4.37.8.
Since it will need some reworking, and due to merge conflicts, a new PR will likely be better.
Check with existing tests to make sure you don't get any of the below:

RuntimeError: coroutine raised StopIteration
ERROR:asyncio:Task was destroyed but it is pending!

(That's worse than any memory leak, as it causes scripts to crash.)

@mdmintz mdmintz closed this Apr 28, 2025
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