You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chrome强制终止后启动显示陈旧界面,CDP数据正常的macOS问题求助

macOS下Chrome非干净退出后的视觉渲染异常问题

我使用nodriver基于Chrome用户配置文件副本驱动真实Chrome,正常运行无问题。但在macOS上,若中途按Ctrl+C强制终止脚本,下次启动时常出现以下视觉异常:

  1. 可见Chrome窗口停留在新标签页(NTP)或之前显示的页面;
  2. 通过CDP读取的DOM为正确的导航页面——document.title、document.URL、元素查询、点击、表单填充、截图(*)均反映真实导航页面,自动化可完整运行;
  3. 点击地址栏时,实际页面UI会从搜索栏“下拉显示”(下拉菜单下方会短暂显示真实页面),或触发渲染器崩溃导致标签页关闭。

(*)Page.captureScreenshot捕获的是真实页面,而非屏幕可见内容。

手动启动Chrome并正常退出后,该问题会消失,直到下次强制终止脚本。说明异常状态由非干净退出保存在配置文件或macOS级Chrome状态中的数据导致。

环境配置

  • 最新版macOS
  • 当前稳定版Google Chrome
  • Python 3.12
  • 当前版本nodriver

每次运行时,我会将真实Chrome的user-data-dir复制到新的tempfile.mkdtemp(...)目录,并使用--profile-directory=Profile 4启动Chrome,确保原配置文件不会被修改。

最小复现示例

import asyncio
import shutil
import tempfile
from pathlib import Path

import nodriver as nd

REAL_BASE = Path("/Users/me/Library/Application Support/Google/Chrome")
PROFILE = "Profile 4"
CHROME = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"


def prepare_temp_profile() -> Path:
    """Copy the real profile to a fresh temp dir (matches what my real code does)."""
    tmp = Path(tempfile.mkdtemp(prefix="repro-chrome-"))

    if (REAL_BASE / "Local State").exists():
        shutil.copy2(REAL_BASE / "Local State", tmp / "Local State")

    shutil.copytree(
        REAL_BASE / PROFILE,
        tmp / PROFILE,
        dirs_exist_ok=True,
        ignore_dangling_symlinks=True,
        ignore=shutil.ignore_patterns("RunningChromeVersion"),
    )
    return tmp


async def main():
    user_data_dir = prepare_temp_profile()

    config = nd.Config(
        headless=False,
        browser_executable_path=CHROME,
        user_data_dir=str(user_data_dir),
        browser_args=[
            f"--profile-directory={PROFILE}",
            "--window-size=1366,768",
        ],
    )

    browser = await nd.start(config=config)
    tab = await browser.get("https://example.org")

    title = await tab.evaluate("document.title")
    url = await tab.evaluate("document.URL")
    print("CDP says title =", title, "| url =", url)

    # Keep window open so you can compare the painted pixels to the CDP truth.
    await asyncio.sleep(120)


if __name__ == "__main__":
    asyncio.run(main())

复现步骤

  1. 运行脚本,验证窗口显示example.org且打印的标题匹配;
  2. 窗口仍打开时按Ctrl+C;
  3. 再次运行脚本,重复步骤2-3几次。

约30%-60%的强制终止后运行会出现窗口停留在陈旧内容的情况,但CDP会正确打印CDP says title = Example Domain | url = https://example.org/。

已尝试但无效的方法

  1. 复制临时目录时排除更多文件,避免上次非干净运行的残留数据。在ignore_patterns(...)中添加了:
    • Singleton*
    • Sessions、Current Session、Current Tabs、Last Session、Last Tabs
    • GPUCache、ShaderCache、GrShaderCache、DawnGraphiteCache、DawnWebGPUCache
    • Crashpad、CrashpadMetrics-active.pma、CrashpadMetrics-spare.pma、Crash Reports
    • lockfile
  2. 修改复制的Preferences,使其看起来像是正常退出,避免Chrome进入崩溃恢复模式:
prefs["profile"]["exit_type"] = "Normal"
prefs["profile"]["exited_cleanly"] = True
prefs["session"]["restore_on_startup"] = 5  # open NTP
prefs["session"]["startup_urls"] = []
  1. 以同样方式修改复制的Local State:
ls["user_experience_metrics"]["stability"]["exited_cleanly"] = True
ls["profile"]["info_cache"]["Profile 4"]["exited_cleanly"] = True
  1. 跳过Chrome启动窗口,避免首次导航是从NTP标签页切换到目标URL——使用--no-startup-window启动Chrome,通过CDP创建第一个标签页(browser.get(url, new_tab=True),底层调用Target.createTarget)。
  2. 添加--disable-session-crashed-bubble启动参数(nodriver默认已添加)。

以上方法均无法改变问题,强制终止后仍会随机触发该异常。

求助内容

在macOS上,除了配置文件JSON退出标记、Sessions/数据、GPU和着色器缓存、渲染器切换路径外,还有哪些Chrome/Chromium状态需要重置才能在非干净退出后恢复合成器?

  • 是否存在Chrome启动参数可禁用跨启动复用的macOS级缓存状态(如~/Library/Saved Application State/com.google.Chrome.savedState/或Core Animation/IOSurface缓存)?
  • 是否可在nd.start()后执行CDP命令,强制窗口重新创建合成器表面(如类似分离+重建、调用Browser.setWindowBounds调整大小、循环执行Emulation.setDeviceMetricsOverride等操作)?
  • 这是否是已知的Chromium Bug?若是,对应的问题编号及 workaround 是什么?

任何关于根因的提示都将非常感谢——我能想到的所有“明显”因素(会话恢复、GPU缓存、着色器缓存、崩溃提示、渲染器切换)似乎都不是问题根源。

浏览器处于异常状态时点击地址栏的现象如下:
Chrome异常状态截图

内容的提问来源于stack exchange,提问作者Ahmed Zaidan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.02 00:07:26