Skip to content

修复 Windows 无页面残留主进程的停止与重启 - #2907

Open
130040167 wants to merge 4 commits into
BigPizzaV3:mainfrom
130040167:codex/fix-windows-codex-restart
Open

130040167 wants to merge 4 commits into
BigPizzaV3:mainfrom
130040167:codex/fix-windows-codex-restart

Conversation

@130040167

@130040167 130040167 commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

现象与原因

Windows 上 Codex 窗口消失后,主进程可能仍然存活,但调试端口没有可注入的主页面。原停止入口会据此提前返回“没有在运行”;重启还可能复用 ready 状态的旧 launcher 会话,继续使用旧启动参数。

停止逻辑还需要区分多个用户、Windows 会话、APPDATA、用户数据目录和 Codex 子进程,不能因为同名进程、坏 argv 或其他实例占用端口而扩大停止范围。

修复

  • Windows 主进程候选先按 ProcessIdToSessionId 过滤,再核对映像、用户、登录会话、APPDATA、用户数据目录和持有句柄;其他会话或已确认无关的坏 argv 不再阻断当前实例。
  • 没有任何存活目标时返回 Codex 没有在运行;存在同映像、同用户但 APPDATA、用户数据目录或其他隔离上下文不一致的主进程时返回明确错误,不静默报告成功。
  • Chromium 身份开关只接受 --key=value 形式;分离参数、空值、重复或歧义值会明确拒绝。
  • launcher 会话保存实际使用过的启动参数和应用目录;停止时已知会话上下文不再无条件读取 SettingsStore,避免启动后设置编辑导致停止错误实例。
  • --user-data-dir 与 CODEX_ELECTRON_USER_DATA_PATH 继续支持,并按实际目录精确匹配;不恢复全局同名进程兜底,也不影响其他目录或 agent 实例。
  • Windows 重启先完成已核验主进程的停止,再走普通启动路径;管理器停止结果区分“没有运行”和“已停止”,并返回实际停止数量。

验证

  • Windows 主停止模块:29 项通过,1 项由父测试显式驱动的集成用例保持 ignored。
  • launcher 测试:38 项通过。
  • 管理器重启回归:8 项通过。
  • Windows release 构建成功,git diff --check 通过。
  • 隔离管理器 UI 冒烟已到达 Tauri/WebView invoke 就绪,并自动处理使用方式选择弹窗;收尾时因 CDP listener 消失而 PID 仍存活,测试器按保护规则保守标记 cleanup_failed,随后确认端口已释放、正式实例和保护文件未变化。

验证边界

  • 本 PR 不宣称覆盖官方 Store/MSIX 默认主实例的完整“停止 → 重启”验收;该链路按本轮范围不再测试。
  • 隔离原生自定义目录场景曾出现停止命令成功返回但实例未退出,未作为运行时通过证据;自定义目录的核心匹配、公共停止 helper 和重复停止边界已由测试覆盖。
  • 尚未证明最初报告的窗口及托盘消失由同一原因触发;本修复针对已确认的停止漏检、上下文误判和旧 launcher 会话复用路径。

@BigPizzaV3

Copy link
Copy Markdown
Owner

感谢!看过了:和 main 无冲突,三平台 CI 全绿。合入前想先对齐两点:

  1. 自定义 user-data-dir 的用户会被挡住:现在只要 codex_extra_args 里有 --user-data-dir,或者设了 CODEX_ELECTRON_USER_DATA_PATH 这类环境变量,停止 / 重启就直接报错。原来这些用户是能正常停止和重启的,升级后会变成用不了。能否对这种情况退回到原来的停止路径(或者至少不报错,只是跳过新的身份核验)?
  2. 默认停止路径的改动面:删掉了 stop_codex_processes_for_debug_port_with_fallback 的全局兜底,重启也从 start_embedded_launcher_for_restart 换成了普通的 start_embedded_launcher,而默认主实例和商店版(MSIX)激活的完整链路还没实测。方便的话请在 Windows 商店版主实例上测一次「停止 → 重启」,结果贴在这里。
    这两点处理完我们就合。

@130040167

Copy link
Copy Markdown
Contributor Author

已推送 1975c0aa,处理自定义目录兼容性问题:

  • 移除了对 --user-data-dir 和 CODEX_ELECTRON_USER_DATA_PATH 的直接拒绝,改为按实际目录精确匹配;不恢复全局同名进程兜底。
  • launcher 保存真正使用过的启动参数,停止时不采用启动后修改的设置。接管会话参数未知时,绑定唯一真实监听者的 PID、创建身份及持有句柄;已知目录也会在停止前核验实际监听者。
  • 停止模块 27 项、launcher 38 项、管理器重启回归 8 项通过;公共停止 API 的真实 helper 测试覆盖默认、显式目录、环境目录和其他实例保留。该提交的 Windows、Linux、macOS CI 均通过。

默认 MSIX 主实例「停止 → 重启」的完整运行验收尚未完成,已在正文明确保留此边界,不作为通过项。沙盒中官方签名包安装成功,但管理器遇到测试环境缺少运行库,尚未进入主实例启停。另有一轮主停止入口作用于隔离多开实例的场景未通过,也已写入正文,不能作为自定义主实例链路通过的证据。

PR 正文已同步最终实现、验证结果与上述限制。

@BigPizzaV3

Copy link
Copy Markdown
Owner

核验链做得很扎实:持句柄比对身份、三次复核、按原句柄终止和等待,误杀其他实例和其他用户进程的路径基本堵住了,非 Windows 行为也保持不变。合并前想请处理几处可用性问题:

  1. 匹配到 0 个主进程时,stop_windows_main_codex_processes_with_args_and_wait 返回 Ok(0),管理器显示「Codex 已停止」。PR 描述里「自定义目录主停止返回成功但实例未退出」应该就是这条。建议:存在同映像、同用户但被跳过的主进程时返回明确错误,说明是哪一项不一致(APPDATA、登录会话、用户数据目录);什么都没运行时沿用「Codex 没有在运行」。
  2. 现在 Windows 重启一定先停止,而停止会被与目标无关的同名进程整体打断:其他用户 / 会话的 ChatGPT.exe 句柄打不开(ACCESS_DENIED)、argv[0] 不是绝对映像路径(执行别名、短路径)、命令行含 --、调试端口为 0 或重复(用户附加参数里自带端口时,主进程会带两个端口参数)。建议先用 ProcessIdToSessionId 排除其他会话;确认不属于本上下文的进程,解析失败时跳过,只对可能是目标的进程失败即停。
  3. Chromium 的开关值需要写成 =,--user-data-dir X 按空格取下一个参数做值与 Chromium 实际行为不一致,建议只认 = 形式,或遇到这种写法直接拒绝。
  4. 会话启动参数已知时,stop_main_codex_process 可以不依赖设置读取成功。
  5. 官方商店包默认主实例的停止和重启验收补完后再合会更稳。

@130040167

Copy link
Copy Markdown
Contributor Author

已按这次回复处理并推送 baf475e2:

  1. 自定义 user-data-dir 兼容性:移除了对 --user-data-dir 和 CODEX_ELECTRON_USER_DATA_PATH 的直接拒绝,改为按实际目录精确匹配;launcher 保存真实启动参数和应用目录,停止时不使用启动后被编辑的设置,也不恢复全局同名进程兜底。
  2. 默认停止路径安全性:候选先按 Windows 会话过滤,再核对映像、用户、APPDATA、用户数据目录和持有句柄;其他会话、其他上下文和无关坏 argv 会跳过,可能属于当前上下文但核验不一致时明确失败。
  3. argv 解析边界:--user-data-dir、--remote-debugging-port、--type 只接受 --key=value;分离参数、空值、重复或歧义值会拒绝。
  4. 已知 launcher 会话:已知实际启动参数和应用目录时,停止不再无条件读取 SettingsStore。

验证结果:Windows 主停止模块 29 项通过(1 项由父测试显式驱动的集成用例保持 ignored)、launcher 38 项通过、管理器重启回归 8 项通过,Windows release 构建和 git diff --check 通过。隔离 UI 冒烟已到达 Tauri/WebView 就绪并处理使用方式弹窗;收尾时 CDP listener 消失而 PID 仍存活,测试器按保护规则保守标记 cleanup_failed,但端口、正式实例和保护文件均已核对无变化。

官方 Store/MSIX 默认主实例完整“停止 → 重启”按本轮范围不再测试,因此不作为通过项。

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants