Skip to content

修复 Windows 多开进程的安全停止边界 - #2735

Open
130040167 wants to merge 10 commits into
BigPizzaV3:mainfrom
130040167:codex/core-process-safety-pr-20261028
Open

130040167 wants to merge 10 commits into
BigPizzaV3:mainfrom
130040167:codex/core-process-safety-pr-20261028

Conversation

@130040167

@130040167 130040167 commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Windows 多开停止只处理桌面根进程时,可能留下 Electron 或内置 app-server 后代;单独使用 PID 或端口清理,又可能误结束已复用 PID 的进程或相邻实例。

本 PR 收紧现有多开停止入口的归属核验与停止边界:

  • 停止入口捕获这一代的桌面进程树,以持有的进程句柄核验创建时间、可执行映像、精确 user-data 和调试参数;可读的 Browser 身份冲突仍拒绝执行。
  • 仅清理已核验的桌面、Electron 后代和安装目录内的内置 app-server,跟踪已捕获后代的退出;不收养 crashpad-handler、终端、MCP 或用户工具,也不据此声称它们已退出。
  • 端口失联时可退回已保存的实例身份,不再以端口唯一监听作为进程归属依据。根进程在核验或停止期间正常退出视为已停止;PID 复用和身份冲突继续拒绝。
  • worker 映像与它自身的 argv[0] 对照,兼容管理器更新后位置不同;缺少 birth id 的旧 worker 清单报错,并在返回失败前记录跳过清理的诊断。
  • worker 停止新增最多约 5 秒同步等待;进程树停止阶段另有最多约 8 秒期限,两者都不是整个停止命令的总耗时上限。

范围仅包含停止安全边界,不改变实例列表状态、终态回执或主实例接管流程。

Windows 验证:

  • cargo test -p codex-plus-core --lib multi_worker --offline:17 项通过,1 项 fixture 入口按设计忽略。覆盖相邻实例、PID 创建身份冲突、短路径、断开的 CDP、并发停止和根进程自然退出。
  • 前端状态测试 5 项、前端生产构建、管理器 debug 构建及 git diff --check 通过。
  • 最终提交构建的隔离管理器启动检查通过,Tauri invoke 就绪;测试进程和端口全部释放,原有实例身份未变。未发送模型请求。

原生进程测试使用受控子进程夹具;未将管理器启动检查表述为真实桌面多开停止的端到端验收。macOS 实机验证仍待完成。

@BigPizzaV3

Copy link
Copy Markdown
Owner

感谢细致的实现,PID 复用和句柄持有的处理思路很好。有一点需要澄清:main 已经在 commands.rs 的多开停止路径上调用 terminate_verified_codex_instance / terminate_verified_worker,所以本 PR 合入后 Windows 多开停止会立即从「结束根进程」变成「结束整棵树并同步等待最多 8 秒」,端口唯一监听的检查也被移除,身份冲突时由 Ok(false) 加诊断日志变成 Err(调用方会忽略这个错误,诊断日志就丢了)。
麻烦在描述里写明这个行为变化,并保留跳过时的诊断日志;另外本 PR 里不少新增公开 API 暂无调用者,建议挪到真正接入的 PR 里一起审,同时说明 crashpad-handler 等未收养进程的预期处理方式。

@130040167
130040167 force-pushed the codex/core-process-safety-pr-20261028 branch from 2ed46f9 to 8d17e18 Compare October 28, 2026 20:05
@BigPizzaV3

Copy link
Copy Markdown
Owner

感谢 rebase!上次提到的几点似乎还没落实:请在描述里写明合入后 Windows 多开停止会从结束根进程变成结束整棵树并同步等待(最多约 8 秒),且不再检查端口唯一监听;身份冲突时请保留跳过的诊断日志(调用方会忽略 Err);暂无调用者的公开 API 建议移到真正接入的 PR;并说明 crashpad-handler 等未收养进程的预期处理方式。谢谢!

@130040167
130040167 force-pushed the codex/core-process-safety-pr-20261028 branch from 8d17e18 to f469d1c Compare October 29, 2026 11:35
@130040167

130040167 commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor Author

已落实这几处:

  • 正文明确现有 Windows 多开停止入口会结束整棵已核验的受管进程树,同步等待最多约 8 秒,并且不再依赖端口唯一监听判断归属。
  • terminate_multi_worker 在返回 Err 前先写 manager.multi_worker_stop_skipped,core 的验证失败路径也保留诊断,避免错误被调用方忽略后无记录。
  • 移除尚未接入的交接 checkpoint、只读 worker 探测及生命周期辅助代码和对应测试,保留当前停止入口实际使用的身份核验与进程树清理。
  • 注释、正文和用例明确 crashpad-handler、终端、MCP 和用户工具不被收养,不以本次清理完成推断它们已退出。

分支已对齐 main 2bf4dfdf。Windows 实跑 cargo test -p codex-plus-core --lib multi_worker --offline:17 项通过、0 项失败,1 项 fixture 入口按设计忽略;管理器 debug 构建和 git diff --check 通过。

@130040167
130040167 force-pushed the codex/core-process-safety-pr-20261028 branch from f469d1c to 8e017d4 Compare October 29, 2026 11:46
@130040167 130040167 changed the title fix(windows): 核验桌面进程树身份并保留交接清理证据 fix(windows): 核验多开进程树身份并安全停止 Oct 29, 2026
@BigPizzaV3

Copy link
Copy Markdown
Owner

感谢落实,诊断和边界说明都很清楚。还有几处小问题:

  1. "main" 实例空 user_data_dir 的特判目前没有调用者,建议移到接入主实例的 PR;
  2. windows_process_tree.rs 第 143 行注释仍写着 worker 在 ready 时捕获,请同步更新;
  3. check_stop_browser_identity / verify_stop_browser 的 cfg 建议改成 any(windows, test),避免 macOS 出现未使用警告;
  4. 请在描述里补上:worker 停止新增最多 5 秒同步等待、映像核验改为对照自身 argv[0]、缺少 birth id 的旧清单改为报错;
  5. 根进程在核验和结束之间刚好退出时,是否可以视为已停止而不报错?

合入前我们也会在 Windows 实机跑一次多开停止。谢谢!

@130040167 130040167 changed the title fix(windows): 核验多开进程树身份并安全停止 修复 Windows 多开进程安全停止与旧实例状态恢复 Oct 29, 2026
@130040167

Copy link
Copy Markdown
Contributor Author

五处均已落实:

  1. 删除无人调用的主实例空 user-data 特判。
  2. 注释改为停止入口捕获和追踪进程树。
  3. 两个 Browser 核验辅助函数的 cfg 改为 any(windows, test)。
  4. 正文补充 worker 最多 5 秒同步等待、映像对照自身 argv[0]、缺少 birth id 的旧 worker 清单报错;树停止阶段另有最多约 8 秒期限,并非整个停止命令的总上限。
  5. 根进程在核验或结束期间正常退出按已停止处理,PID 复用及其他身份冲突仍拒绝;新增原生子进程回归,保留并发停止及已捕获后代清理测试。

同时保留并补测停止回执与旧实例状态校准,分支包含 main b70bcf26。Windows 进程测试 18 项、回执校准测试 4 项、前端状态测试 5 项全部通过;前端和管理器 debug 构建、git diff --check 通过。

最终提交构建另做了独立原生管理器验收:同代已停止记录不再出现在当前实例列表,页面重载不复现;旧代回执和清理失败仍可见。场景整体通过,测试进程树和端口清理完成,原有实例身份未变,未发送模型请求。完整桌面重启和管理器更新续接不作为本 PR 的验收结论。

@BigPizzaV3

Copy link
Copy Markdown
Owner

五处都看到了,谢谢!不过新加的停止回执校准有个问题:现有 worker 和停止流程都不会写 stopped / cleanup_failed 回执,multi_instance_snapshot_status 会把所有已关闭、回执仍为 ready 的实例判成 unknown,前端又显示所有非 stopped 的实例,结果正常结束的实例会一直留在列表里、点结束也清不掉(macOS 也一样)。建议把这部分(835fbdd1b 及对应的前端改动)拆到另一个 PR,并补上写回执的一方;本 PR 只保留停止边界。另外 macOS 测试构建下 arguments_use_user_data 有未使用警告。谢谢!

@130040167 130040167 changed the title 修复 Windows 多开进程安全停止与旧实例状态恢复 修复 Windows 多开进程的安全停止边界 Oct 29, 2026
@130040167

130040167 commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor Author

已将停止回执校准及对应前端改动完整移出,#2735 现在只保留停止安全边界。移出后 arguments_use_user_data 不再存在,macOS 测试构建的该处未使用警告随之消除;之前确认的五项停止边界修正均保留。

收窄后的分支重新验证:Windows multi_worker 测试 17 项通过,1 项 fixture 入口忽略;前端状态测试 5 项、前端生产构建、管理器 debug 构建及差异检查通过。隔离管理器启动通过,测试进程与端口清理完成,原有实例身份未变。

回执读写闭环已拆为独立草稿 #2784,覆盖管理器停止与原生关闭后的终态写入、失败保留与同代持久化。该草稿依赖本 PR,管理器自身退出策略保持现有行为;本 PR 仅保留停止安全边界。

@BigPizzaV3

Copy link
Copy Markdown
Owner

收窄后的 diff 看过了,回执校准已经完整移出,macOS 上 multi_worker 测试通过、没有警告,代码上可以合入。一个可选的小点:valid_stop_identity / record_stop_verification_failure 在 Linux 普通构建下没有调用方,会出未使用警告,方便的话加上 #[cfg(any(windows, target_os = "macos", test))]。

这个 PR 改的是 Windows 上结束进程的边界,我们正在准备发布新版本,为避免临发版扩大范围,会在这次发版之后合入。谢谢!

@130040167

Copy link
Copy Markdown
Contributor Author

已为 valid_stop_identity 和 record_stop_verification_failure 增加 #[cfg(any(windows, target_os = "macos", test))],限定到实际调用平台与测试,避免 Linux 普通构建下的未使用警告。停止边界和现有行为保持一致。

Windows multi_worker 测试 17 项通过、1 项 fixture 入口按设计忽略;管理器 debug 构建及差异检查通过。最终提交构建的隔离管理器启动就绪,测试进程和端口清理完成,原有实例身份未变。

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