Skip to content
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

Xvfb display not terminated on cdp_driver stop, causing potential memory leak #3618

Closed
montovaneli opened this issue Mar 20, 2025 · 1 comment
Labels
question Someone is looking for answers UC Mode / CDP Mode Undetected Chromedriver Mode / CDP Mode

Comments

@montovaneli
Copy link

When running the cdp driver with the xvfb=True option, the Xvfb display process is not terminated after calling driver.stop(). This results in an increasing number of Xvfb processes when running scrapers in an infinite loop, potentially leading to a memory leak.

Environment:
OS: Ubuntu 22.04
Python: 3.10.12
Latest SeleniumBase

Steps to Reproduce:

Run the following code example:

import asyncio
import subprocess

from seleniumbase.undetected import cdp_driver


async def main():
    driver = await cdp_driver.cdp_util.start_async(xvfb=True)
    page = await driver.get("about:blank")
    await page.sleep(2)
    driver.stop()

def count_xvfb_processes():
    try:
        cmd = "ps aux | grep Xvfb | grep -v grep | wc -l"
        result = subprocess.run(
            cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True,
            shell=True,
        )
        count = result.stdout.strip()
        print(f"Number of Xvfb processes running: {count}")
        return int(count)
    except Exception as e:
        print(f"Error counting Xvfb processes: {e}")
        return -1

if __name__ == "__main__":
    i = 0
    while i < 10:
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        loop.run_until_complete(main())

        # Count Xvfb processes
        count_xvfb_processes()
        i += 1

Notice that after each iteration, the number of running Xvfb processes increases.

Expected Behavior:
The Xvfb display process should be terminated when driver.stop() is called, ensuring that no residual Xvfb processes remain active.

Actual Behavior:
Xvfb processes continue to run after driver.stop(), leading to an accumulation of processes which may cause a memory leak over time, particularly in scrapers running in an infinite loop.

Thank you for your amazing work!

@mdmintz mdmintz added question Someone is looking for answers UC Mode / CDP Mode Undetected Chromedriver Mode / CDP Mode labels Mar 20, 2025
@mdmintz
Copy link
Member

mdmintz commented Mar 20, 2025

The Xvfb virtual display gets saved to sb_config._virtual_display:

sb_config._virtual_display = _xvfb_display

So you can call quit(), (or equivalent), from that object.

Since multiple drivers running in parallel could be using the same virtual display, it doesn't make sense to quit the virtual display if the driver is quit (because another driver might be using it). Therefore, quit the display separately when it's no longer needed.

To access sb_config use:

from seleniumbase import config as sb_config

@mdmintz mdmintz closed this as completed Mar 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Someone is looking for answers UC Mode / CDP Mode Undetected Chromedriver Mode / CDP Mode
Projects
None yet
Development

No branches or pull requests

2 participants