Improve BrowserLauncher cleanup handling

This commit is contained in:
程序员阿江-Relakkes
2025-09-26 16:52:38 +08:00
parent 7b9db2f748
commit 3237073a0e
2 changed files with 69 additions and 27 deletions
+48 -18
View File
@@ -14,6 +14,7 @@ import platform
import subprocess import subprocess
import time import time
import socket import socket
import signal
from typing import Optional, List, Tuple from typing import Optional, List, Tuple
import asyncio import asyncio
from pathlib import Path from pathlib import Path
@@ -106,7 +107,7 @@ class BrowserLauncher:
raise RuntimeError(f"无法找到可用的端口,已尝试 {start_port} 到 {port-1}") raise RuntimeError(f"无法找到可用的端口,已尝试 {start_port} 到 {port-1}")
def launch_browser(self, browser_path: str, debug_port: int, headless: bool = False, def launch_browser(self, browser_path: str, debug_port: int, headless: bool = False,
user_data_dir: Optional[str] = None) -> subprocess.Popen: user_data_dir: Optional[str] = None) -> subprocess.Popen:
""" """
启动浏览器进程 启动浏览器进程
@@ -169,7 +170,8 @@ class BrowserLauncher:
stderr=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
preexec_fn=os.setsid # 创建新的进程组 preexec_fn=os.setsid # 创建新的进程组
) )
self.browser_process = process
return process return process
except Exception as e: except Exception as e:
@@ -230,20 +232,48 @@ class BrowserLauncher:
""" """
清理资源,关闭浏览器进程 清理资源,关闭浏览器进程
""" """
if self.browser_process: if not self.browser_process:
try: return
utils.logger.info("[BrowserLauncher] 正在关闭浏览器进程...")
process = self.browser_process
if self.system == "Windows":
# Windows下使用taskkill强制终止进程树 if process.poll() is not None:
subprocess.run(["taskkill", "/F", "/T", "/PID", str(self.browser_process.pid)], utils.logger.info("[BrowserLauncher] 浏览器进程已退出,无需清理")
capture_output=True) self.browser_process = None
return
utils.logger.info("[BrowserLauncher] 正在关闭浏览器进程...")
try:
if self.system == "Windows":
# 先尝试正常终止
process.terminate()
try:
process.wait(timeout=5)
except subprocess.TimeoutExpired:
utils.logger.warning("[BrowserLauncher] 正常终止超时,使用taskkill强制结束")
subprocess.run(
["taskkill", "/F", "/T", "/PID", str(process.pid)],
capture_output=True,
check=False,
)
process.wait(timeout=5)
else:
pgid = os.getpgid(process.pid)
try:
os.killpg(pgid, signal.SIGTERM)
except ProcessLookupError:
utils.logger.info("[BrowserLauncher] 浏览器进程组不存在,可能已退出")
else: else:
# Unix系统下终止进程组 try:
os.killpg(os.getpgid(self.browser_process.pid), 9) process.wait(timeout=5)
except subprocess.TimeoutExpired:
self.browser_process = None utils.logger.warning("[BrowserLauncher] 优雅关闭超时,发送SIGKILL")
utils.logger.info("[BrowserLauncher] 浏览器进程已关闭") os.killpg(pgid, signal.SIGKILL)
process.wait(timeout=5)
except Exception as e:
utils.logger.warning(f"[BrowserLauncher] 关闭浏览器进程时出错: {e}") utils.logger.info("[BrowserLauncher] 浏览器进程已关闭")
except Exception as e:
utils.logger.warning(f"[BrowserLauncher] 关闭浏览器进程时出错: {e}")
finally:
self.browser_process = None
+21 -9
View File
@@ -291,16 +291,28 @@ class CDPBrowserManager:
""" """
try: try:
# 关闭浏览器上下文 # 关闭浏览器上下文
# if self.browser_context: if self.browser_context:
# await self.browser_context.close() try:
# self.browser_context = None await self.browser_context.close()
# utils.logger.info("[CDPBrowserManager] 浏览器上下文已关闭") utils.logger.info("[CDPBrowserManager] 浏览器上下文已关闭")
except Exception as context_error:
utils.logger.warning(
f"[CDPBrowserManager] 关闭浏览器上下文失败: {context_error}"
)
finally:
self.browser_context = None
# # 断开浏览器连接 # 断开浏览器连接
# if self.browser: if self.browser:
# await self.browser.close() try:
# self.browser = None await self.browser.close()
# utils.logger.info("[CDPBrowserManager] 浏览器连接已断开") utils.logger.info("[CDPBrowserManager] 浏览器连接已断开")
except Exception as browser_error:
utils.logger.warning(
f"[CDPBrowserManager] 关闭浏览器连接失败: {browser_error}"
)
finally:
self.browser = None
# 关闭浏览器进程(如果配置为自动关闭) # 关闭浏览器进程(如果配置为自动关闭)
if config.AUTO_CLOSE_BROWSER: if config.AUTO_CLOSE_BROWSER: