CDP browser manager, responsible for launching and managing browsers connected via CDP
| 33 | |
| 34 | |
| 35 | class CDPBrowserManager: |
| 36 | """ |
| 37 | CDP browser manager, responsible for launching and managing browsers connected via CDP |
| 38 | """ |
| 39 | |
| 40 | def __init__(self): |
| 41 | self.launcher = BrowserLauncher() |
| 42 | self.browser: Optional[Browser] = None |
| 43 | self.browser_context: Optional[BrowserContext] = None |
| 44 | self.debug_port: Optional[int] = None |
| 45 | self._cleanup_registered = False |
| 46 | |
| 47 | def _register_cleanup_handlers(self): |
| 48 | """ |
| 49 | Register cleanup handlers to ensure browser process cleanup on program exit |
| 50 | """ |
| 51 | if self._cleanup_registered: |
| 52 | return |
| 53 | |
| 54 | def sync_cleanup(): |
| 55 | """Synchronous cleanup function for atexit""" |
| 56 | if self.launcher and self.launcher.browser_process: |
| 57 | utils.logger.info("[CDPBrowserManager] atexit: Cleaning up browser process") |
| 58 | self.launcher.cleanup() |
| 59 | |
| 60 | # Register atexit cleanup |
| 61 | atexit.register(sync_cleanup) |
| 62 | |
| 63 | # Register signal handlers (only when no custom handlers exist, to avoid overriding main entry signal handling logic) |
| 64 | prev_sigint = signal.getsignal(signal.SIGINT) |
| 65 | prev_sigterm = signal.getsignal(signal.SIGTERM) |
| 66 | |
| 67 | def signal_handler(signum, frame): |
| 68 | """Signal handler""" |
| 69 | utils.logger.info(f"[CDPBrowserManager] Received signal {signum}, cleaning up browser process") |
| 70 | if self.launcher and self.launcher.browser_process: |
| 71 | self.launcher.cleanup() |
| 72 | |
| 73 | if signum == signal.SIGINT: |
| 74 | if prev_sigint == signal.default_int_handler: |
| 75 | return prev_sigint(signum, frame) |
| 76 | raise KeyboardInterrupt |
| 77 | |
| 78 | raise SystemExit(0) |
| 79 | |
| 80 | install_sigint = prev_sigint in (signal.default_int_handler, signal.SIG_DFL) |
| 81 | install_sigterm = prev_sigterm == signal.SIG_DFL |
| 82 | |
| 83 | # Register SIGINT (Ctrl+C) and SIGTERM |
| 84 | if install_sigint: |
| 85 | signal.signal(signal.SIGINT, signal_handler) |
| 86 | else: |
| 87 | utils.logger.info("[CDPBrowserManager] SIGINT handler already exists, skipping registration to avoid override") |
| 88 | |
| 89 | if install_sigterm: |
| 90 | signal.signal(signal.SIGTERM, signal_handler) |
| 91 | else: |
| 92 | utils.logger.info("[CDPBrowserManager] SIGTERM handler already exists, skipping registration to avoid override") |
no outgoing calls