Skip to content

fix(tools): 取消 exec 时终止整棵进程树(Windows) - #152

Merged
countbot-ai merged 1 commit into
mainfrom
fix/exec-cancel-windows
Oct 30, 2026
Merged

countbot-ai merged 1 commit into
mainfrom
fix/exec-cancel-windows

Conversation

@countbot-ai

Copy link
Copy Markdown
Owner

变更说明

合并 #151 后,main 上第一次 CI 在 Windows 只挂了一条:

tests/test_tool_boundaries.py::test_exec_terminates_process_on_cancel - TimeoutError
1 failed, 707 passed

日志里同时出现 Terminate orphan process: pid (2036) (sleep),说明被取消的命令进程活到了 job 收尾。

根因

_terminate_process() 的 Windows 分支只对 shell 本体 terminate() / kill():

  • start_new_session=True(创建子进程时传入)是 POSIX 专有参数,Windows 直接忽略,所以没有「进程组」可用;
  • cmd.exe /c sleep 30 被结束后,sleep.exe 成为孤儿,继续持有继承来的 stdout/stderr 管道;
  • _collect_process_output() 读不到 EOF,取消后的调用一直挂着,直到外层超时才返回。

对桌面版的实际影响:Windows 上点停止,命令其实还在跑,工具调用卡到超时。

修改

_terminate_process() 在 Windows 上改走 _kill_process_tree_windows():taskkill /F /T /PID <pid> 递归结束整棵进程树,失败再退回单进程 kill()。POSIX 分支(SIGTERM → SIGKILL 按进程组)保持不变。

验证

  • 本地 macOS:pytest tests 708 passed(Python 3.11 与 3.12 各一遍)
  • POSIX 路径未改动,回归风险集中在 Windows 分支,交由 CI 的 windows-latest 验证

_terminate_process 的 Windows 分支只 terminate()/kill() 了 cmd.exe,而
start_new_session 是 POSIX 专有参数,Windows 下不生效,sleep / npm 这类
子进程会存活并继续持有继承来的 stdout/stderr 管道。等待输出的一方读不到
EOF,取消后调用要挂到超时才返回,子进程则在后台继续跑。

改为 Windows 上走 taskkill /F /T /PID 递归结束进程树,失败再退回单进程
kill。对应测试 test_exec_terminates_process_on_cancel 在 Windows CI 上
正是超时失败。
@countbot-ai
countbot-ai merged commit 2223ce8 into main Oct 30, 2026
2 checks passed
@countbot-ai
countbot-ai deleted the fix/exec-cancel-windows branch October 30, 2026 02:40
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.

1 participant