File descriptors leak in undetected (UC) mode #3679
Replies: 7 comments 7 replies
-
Do you know how to find specifically the code where the file descriptors leaks occur? The specific locations would be helpful. Much of UC Mode / CDP Mode is based on |
Beta Was this translation helpful? Give feedback.
-
Hello @mdmintz, Thank you for your response. I spent several hours debugging and have identified a number of issues: 1. Session-based requests Original SeleniumBase/seleniumbase/undetected/cdp.py Line 104 in b9a89f7 Updated You can review all of my changes here: With these adjustments, the leak in uc_open_with_reconnect no longer occurs (even without invoking the garbage collector), and the number of leaked file descriptors in activate_cdp_mode is greatly reduced. 2. Remaining leak in activate_cdp_mode It appears that each of these functions establishes its own socket connection, which is never closed. Moreover, I have confirmed that the corresponding stop method (at line 569) is never invoked, which I believe is the underlying cause of the remaining leak:
FD=6 and FD=7 are the two socks that do not close, and this is the trace of when each is called
|
Beta Was this translation helpful? Give feedback.
-
CDP Mode memory improvements will have to be figured out later. |
Beta Was this translation helpful? Give feedback.
-
Hey @mdmintz, Thank you for the update. After running some additional tests I’ve traced the file‑descriptor leak to the Connection class. Although an aclose() coroutine exists, it’s never invoked. The aexit() method would normally trigger aclose(), but it only executes when Connection is used as an async context manager—which isn’t happening in the current workflow. To prevent the leak it will need to make sure every connection is explicitly closed, either by:
|
Beta Was this translation helpful? Give feedback.
-
Fixed in |
Beta Was this translation helpful? Give feedback.
-
Hey @mdmintz, While deploying to production today I noticed that we’re still seeing a connection leak on the CDP side. It appears to originate around From what I can tell, the flow calls start() and then get(), which opens two separate WebSocket connections. The recent patch only closes the most recently opened socket via sb_config._cdp_aclose = self.aclose, leaving the first one dangling.for i in range(1, 4):
print(f"\nIteration {i}")
with SB(
uc=True,
) as browser:
browser.activate_cdp_mode("https://bloomberg.com/news/articles/2024-12-05/barclays-promotes-116-staffers-across-bank-to-managing-director")
browser.sleep(5)
browser.cdp.get_page_source()
inspect_fds()
|
Beta Was this translation helpful? Give feedback.
-
Hey @mdmintz, I apologise for the delayed response. I was only able to replicate this issue with heavy websites as Bloomberg and WSJ, because they use a lot of iframes and background services. I’ve completed my investigation and implemented the following fixes:
With these changes, both the connection and FD leaks no longer occur in my tests. Replicate:Add a print after this line: print("aopen", self.websocket_url) And another after this line print("aclose", self.websocket_url) Output:
Add this print after this line print(f"Tab: {websocket_url}") Output:
AFTER THE FIX:
My branch: master...felipehertzer:SeleniumBase:master |
Beta Was this translation helpful? Give feedback.
-
Hi,
I’m seeing a steady increase in open file descriptors whenever I activate UC mode (uc=True), leading eventually to:
When UC mode is off the FD count remains flat.
When I use uc_open_with_reconnect and force a gc.collect() after teardown, the leak stops.
Below are three minimal repros—please let me know what else I can provide.
CDP
This script repeatedly opens a browser, calls activate_cdp_mode(...), then quits. You can see the number of FDs jump by ~8–10 each time, and connections in CLOSE_WAIT remain.
Output:
UC without GC
Here we use uc_open_with_reconnect(...) instead of CDP. The leak still occurs, growing by ~1 FD per iteration.
Output:
UC using GC
Adding a manual garbage collection after each teardown appears to reclaim all sockets—FD count stays constant. But it only works for uc_open_with_reconnect.
Output:
Environment:
SeleniumBase version: e.g. 4.37.2
Python version: e.g. 3.13
OS: MacOS and Linux
Chrome: 135.0.7049.85
Chromedriver: matching Chrome
Beta Was this translation helpful? Give feedback.
All reactions