Skip to content

Commit 8d4839e

Browse files
authored
Merge pull request #4350 from seleniumbase/cdp-mode-patch-106
CDP Mode: Patch 106
2 parents be79594 + b328370 commit 8d4839e

7 files changed

Lines changed: 55 additions & 9 deletions

File tree

help_docs/cdp_mode_methods.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ sb.cdp.open(url, **kwargs) # Same as sb.cdp.get(url, **kwargs)
1212
sb.cdp.reload(ignore_cache=True, script_to_evaluate_on_load=None)
1313
sb.cdp.refresh(*args, **kwargs)
1414
sb.cdp.get_event_loop()
15+
sb.cdp.is_running()
1516
sb.cdp.get_rd_host() # Returns the remote-debugging host
1617
sb.cdp.get_rd_port() # Returns the remote-debugging port
1718
sb.cdp.get_rd_url() # Returns the remote-debugging URL

mkdocs_build/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
regex>=2026.5.9
55
pymdown-extensions>=10.21.3
6-
pipdeptree>=2.35.2
6+
pipdeptree>=2.35.3
77
python-dateutil>=2.8.2
88
Markdown==3.10.2
99
click==8.4.0

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ six>=1.17.0
2424
parse>=1.22.0
2525
parse-type>=0.6.6
2626
colorama>=0.4.6
27+
psutil>=7.2.2
2728
pyyaml>=6.0.3
2829
pygments>=2.20.0
2930
pyreadline3>=3.5.4;platform_system=="Windows"

seleniumbase/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# seleniumbase package
2-
__version__ = "4.49.0"
2+
__version__ = "4.49.1"

seleniumbase/undetected/__init__.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import logging
22
import os
33
import re
4+
import psutil
45
import requests
56
import subprocess
67
import sys
@@ -299,6 +300,13 @@ def __init__(
299300
creationflags=creationflags,
300301
)
301302
self.browser_pid = browser.pid
303+
self._process_pid = browser.pid
304+
try:
305+
self._process_create_time = (
306+
psutil.Process(self._process_pid).create_time()
307+
)
308+
except psutil.NoSuchProcess:
309+
self._process_create_time = None
302310
service_ = None
303311
log_output = subprocess.PIPE
304312
if patch_driver:
@@ -392,6 +400,22 @@ def _hook_remove_cdc_props(self, cdc_props):
392400
},
393401
)
394402

403+
def is_running(self):
404+
"""Check if the browser is still running."""
405+
if not getattr(self, "_process_pid", None):
406+
return False
407+
# Not good enough: return psutil.pid_exists(self._process_pid)
408+
try:
409+
process = psutil.Process(self._process_pid)
410+
# Check for PID recycling: Is this actually our process?
411+
if hasattr(self, "_process_create_time"):
412+
if process.create_time() != self._process_create_time:
413+
return False # The PID was reused by a different process!
414+
# If the process is a zombie, assume the browser isn't running
415+
return process.status() != psutil.STATUS_ZOMBIE
416+
except psutil.NoSuchProcess:
417+
return False
418+
395419
def remove_cdc_props_as_needed(self):
396420
cdc_props = self._get_cdc_props()
397421
if len(cdc_props) > 0:

seleniumbase/undetected/cdp_driver/browser.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import os
1010
import pathlib
1111
import pickle
12+
import psutil
1213
import re
1314
import shutil
1415
import time
@@ -263,6 +264,22 @@ async def _handle_target_update(
263264
)
264265
self.targets.remove(current_tab)
265266

267+
def is_running(self):
268+
"""Check if the browser is still running."""
269+
if not getattr(self, "_process_pid", None):
270+
return False
271+
# Not good enough: return psutil.pid_exists(self._process_pid)
272+
try:
273+
process = psutil.Process(self._process_pid)
274+
# Check for PID recycling: Is this actually our process?
275+
if hasattr(self, "_process_create_time"):
276+
if process.create_time() != self._process_create_time:
277+
return False # The PID was reused by a different process!
278+
# If the process is a zombie, assume the browser isn't running
279+
return process.status() != psutil.STATUS_ZOMBIE
280+
except psutil.NoSuchProcess:
281+
return False
282+
266283
def get_rd_host(self):
267284
return self.config.host
268285

@@ -617,6 +634,12 @@ async def start(self=None) -> Browser:
617634
)
618635
await asyncio.sleep(0.05)
619636
self._process_pid = self._process.pid
637+
try:
638+
self._process_create_time = (
639+
psutil.Process(self._process_pid).create_time()
640+
)
641+
except psutil.NoSuchProcess:
642+
self._process_create_time = None
620643
await asyncio.sleep(0.05)
621644
self._http = HTTPApi((self.config.host, self.config.port))
622645
await asyncio.sleep(0.05)

setup.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -182,11 +182,12 @@
182182
'typing-extensions>=4.15.0',
183183
'sbvirtualdisplay>=1.4.0',
184184
'MarkupSafe>=3.0.3',
185-
"Jinja2>=3.1.6",
186-
"six>=1.17.0",
185+
'Jinja2>=3.1.6',
186+
'six>=1.17.0',
187187
'parse>=1.22.0',
188188
'parse-type>=0.6.6',
189189
'colorama>=0.4.6',
190+
'psutil>=7.2.2',
190191
'pyyaml>=6.0.3',
191192
'pygments>=2.20.0',
192193
'pyreadline3>=3.5.4;platform_system=="Windows"',
@@ -303,11 +304,7 @@
303304
# pip install -e .[playwright]
304305
# (For the Playwright integration.)
305306
"playwright": [
306-
"playwright>=1.58.0",
307-
],
308-
# pip install -e .[psutil]
309-
"psutil": [
310-
"psutil>=7.2.2",
307+
"playwright>=1.60.0",
311308
],
312309
# pip install -e .[pyautogui]
313310
# (Already a required dependency on Linux now.)

0 commit comments

Comments
 (0)