diff --git a/utils/markdown_to_image.py b/utils/markdown_to_image.py index 1737ae8..e3b107b 100644 --- a/utils/markdown_to_image.py +++ b/utils/markdown_to_image.py @@ -39,15 +39,40 @@ async def safe_close_browser(browser, timeout: float = 4.0) -> None: try: parent = psutil.Process(browser.process.pid) children = parent.children(recursive=True) - for child in children: + + # 3.1 try graceful terminate first + for proc in children: try: - child.kill() - except psutil.NoSuchProcess: + proc.terminate() + except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): pass - parent.kill() - # 可选:等待一小会儿确认退出 - psutil.wait_procs([parent] + children, timeout=3) - logger.debug("process tree killed") + try: + parent.terminate() + except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): + pass + + # 3.2 wait briefly, then force kill + try: + gone, alive = psutil.wait_procs([parent] + children, timeout=2) + except Exception: + gone, alive = [], [parent] + children + + for proc in alive: + try: + proc.kill() + except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): + pass + + # 3.3 final wait and report + try: + gone, alive = psutil.wait_procs([parent] + children, timeout=3) + except Exception: + alive = [] + + if alive: + logger.warning(f"process still alive after kill: {[p.pid for p in alive]}") + else: + logger.debug("process tree terminated") except (psutil.NoSuchProcess, Exception) as e: logger.warning(f"force kill failed: {e}")