From 23d2f2562e8ca35b2fe5b6c65ebea6e789a3ab71 Mon Sep 17 00:00:00 2001 From: liuwei Date: Fri, 17 Apr 2026 11:46:35 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=AF=E7=94=A8md2img=E5=BC=BA=E4=BF=9D?= =?UTF-8?q?=E6=B4=BB=E6=A8=A1=E5=BC=8F=EF=BC=9A=E7=A7=BB=E9=99=A4=E6=B5=8F?= =?UTF-8?q?=E8=A7=88=E5=99=A8=E4=B8=BB=E5=8A=A8=E5=85=B3=E9=97=AD=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. safe_close_browser 改为保活模式下直接返回,不执行 browser.close\n2. 去除 safe_close_browser 中的 terminate/kill 进程树逻辑\n3. 保留函数签名与调用链,确保现有流程兼容\n4. 增加中文注释说明长期常驻场景下的设计意图 --- utils/markdown_to_image.py | 60 ++++++-------------------------------- 1 file changed, 9 insertions(+), 51 deletions(-) diff --git a/utils/markdown_to_image.py b/utils/markdown_to_image.py index 9e4f71c..8fd377a 100644 --- a/utils/markdown_to_image.py +++ b/utils/markdown_to_image.py @@ -120,59 +120,17 @@ def _simple_markdown_to_html(md_content: str) -> str: async def safe_close_browser(browser, timeout: float = 4.0) -> None: + """保活优先:不执行浏览器关闭。 + + 设计说明: + 1. 当前业务要求浏览器进程长期常驻,因此这里显式禁用“主动关闭进程”; + 2. 即使上层调用了 safe_close_browser,也只记录日志并直接返回; + 3. 保留函数签名是为了兼容现有调用点,避免大范围改动影响稳定性。 + """ if not browser: return - - for context in browser.contexts[:]: - for page in context.pages[:]: - try: - await asyncio.wait_for(page.close(), timeout=1.5) - except Exception: - pass - try: - await asyncio.wait_for(context.close(), timeout=timeout) - except Exception: - pass - - try: - await asyncio.wait_for(browser.close(), timeout=timeout) - logger.debug("browser closed gracefully") - return - except (asyncio.TimeoutError, Exception) as e: - logger.warning(f"browser.close failed: {e}") - - if browser.process and browser.process.pid: - try: - parent = psutil.Process(browser.process.pid) - children = parent.children(recursive=True) - for proc in children: - try: - proc.terminate() - except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): - pass - try: - parent.terminate() - except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): - pass - 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 - 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}") + logger.info("[md2img] 保活模式:跳过 safe_close_browser,不主动关闭浏览器进程") + return def _clean_text(html: str) -> str: