Skip to content

已定位:子进程 os.kill(pid,0) 广播 Ctrl+C 导致宿主整体退出(Windows) #208

Closed

Description

@djs326

更新:根因已定位(附完整证据链)

在 stock 官方版与纯 seam 层复现后,崩溃机制已修正——之前报告中的归因(os.kill(pid, 0) 走 TerminateProcess)不准确,实际是 Ctrl+C 控制台广播。以下是完整证据与修正后的根因分析。

复现矩阵(全部实测)

环境 结果
桌面版(dataelement/dsh-desktop)执行 _pid_is_alive(os.getpid()) 崩溃(两次,需重启)
stock 官方 dsh web(0.1.1-rc.2,独立 DSH_HOME,不经桌面壳)执行同命令 崩溃(两次),无任何 stderr 输出
纯 seam 脚本:直接调用 @deepseek-ai/dsh-subprocess-local spawn 自杀 python(不经 web/agent/桌面壳) 宿主 node 进程静默退出,无任何事件/日志
同控制台的 PowerShell 后续命令也被打断(Ctrl+C 广播波及)
_pid_is_alive(17576) / _pid_is_alive(999999999)(PID 不存在) 正常返回 False,无任何影响
python --version(正常退出的子进程) 完全正常,宿主存活

关键退出码

纯 seam 脚本宿主进程的 $LASTEXITCODE = -1073741510 = 0xC000013A = STATUS_CONTROL_C_EXIT(被 Ctrl+C 终止)。第二次运行时连 PowerShell 命令行的后续命令都被打断——证明 Ctrl+C 事件广播到了整个共享控制台。

根因链

  1. Python 侧(触发方):Windows 上 os.kill(pid, 0) 的 sig=0 恰好等于 signal.CTRL_C_EVENT(已实测:CTRL_C_EVENT = 0)。Python 对 CTRL_C_EVENT/CTRL_BREAK_EVENT 走 GenerateConsoleCtrlEvent(sig, pid) 分支(TerminateProcess 只用于其他 sig 值)。因此 os.kill(pid, 0) 的真实语义是:向与 pid 共享同一控制台的所有进程广播 Ctrl+C,而不是 POSIX 的"存活探测"。
  2. DSH 侧:@deepseek-ai/dsh-subprocess-local 的 spawn 在 Windows 上使用 detached: false(lib/index.js:805:detached: platform !== "win32")→ 子进程与宿主共享同一控制台。子进程执行 os.kill(自己的pid, 0) 时,Ctrl+C 广播直接命中宿主。
  3. 宿主侧:node 默认的 Ctrl+C 处理是立即退出且无任何日志——这正是此前所有"静默崩溃"(无 stderr)现象的原因。

结论与修复建议(更新)

  • 维持 weijiafu14 / denial123789 的意见:不加全局 uncaughtException / unhandledRejection 兜底(那是最后边界,不是修复手段)。
  • 根因修复候选:
    • DSH spawn 在 Windows 上为子进程创建独立进程组/控制台(CREATE_NEW_PROCESS_GROUP / detached: true),使子进程的 GenerateConsoleCtrlEvent 无法波及宿主;
    • 或宿主进程调用 SetConsoleCtrlHandler(NULL, TRUE) 忽略 CTRL_C_EVENT(适用于可控场景);
    • 子进程输出流的 'error' 监听与句柄清理仍建议补(EPIPE 路径),但不是本问题的根因。
  • 触发方(douyin-sparkflow 的 launcher.py):os.kill(pid, 0) 存活探测在 Windows 上不可用(语义=Ctrl+C 广播),应改用 OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION) + GetExitCodeProcess,或 psutil。此坑会单独提交到其仓库。

对维护者的请求

  • 确认 Windows 上 spawn 的控制台共享策略(detached: false)是有意设计还是疏忽;
  • 现有的 Host-survival 回归门(19 项)似乎未覆盖"子进程向共享控制台广播 Ctrl+C"这一场景,建议补充。

四层进程身份记录(按 denial123789 的建议)

  • 第三方 child(python,venv 解释器):退出(Ctrl+C 广播同时命中自身)
  • 官方 DSH Host(纯 seam 脚本 node 进程,PID 448 / 11376):退出码 0xC000013A(STATUS_CONTROL_C_EXIT)静默退出
  • 桌面 main process(dataelement/dsh-desktop):崩溃(退出码未捕获,用户观察)
  • renderer:断连(用户观察)

Activity

  1. yyang8891 commented on Aug 27, 2026

    @yyang8891

    这种问题vs code都会出现,是模型的问题,不是桌面端工具的问题

  2. changed the title [-]子进程异常终止(被强杀)导致 DSH Desktop 整个崩溃(Windows)[/-] [+]已定位:子进程 os.kill(pid,0) 广播 Ctrl+C 导致宿主整体退出(Windows)[/+] on Aug 27, 2026
  3. djs326 commented on Aug 27, 2026

    @djs326
    Author

    更新(2026-08-27):stock 官方版复现完成,归属与根因已修正。

    按维护者的建议,我们在 stock 官方 dsh(0.1.1-rc.2,npm 全局安装,独立 DSH_HOME,不经桌面壳)上复现了同一条命令——stock 同样崩溃。随后用独立 Node 脚本直接调用官方 seam(@deepseek-ai/dsh-subprocess-local)spawn 自杀子进程,宿主 node 进程以退出码 0xC000013A(STATUS_CONTROL_C_EXIT,被 Ctrl+C 终止)静默退出,同控制台的 PowerShell 命令行也被打断。

    根因修正(之前报告写的"os.kill 走 TerminateProcess"不准确):

    • Windows 上 signal.CTRL_C_EVENT = 0,因此 os.kill(pid, 0) 的 sig=0 恰好等于 CTRL_C_EVENT,Python 走的是 GenerateConsoleCtrlEvent(CTRL_C_EVENT, pid)——向共享同一控制台的所有进程广播 Ctrl+C;
    • dsh-subprocess-local 在 Windows 上 spawn 使用 detached: false(lib/index.js:805),子进程与宿主共享控制台,广播一发即中,宿主被 Ctrl+C 静默杀死。

    回应 @yyang8891 的评论:这不是"模型的问题"——模型只是执行了命令;根因是 Python 在 Windows 的 os.kill API 语义坑 + 宿主未做控制台隔离。VS Code 也会出现类似现象,恰好说明这是 Windows 共享控制台的共性问题;但对一个承诺"宿主存活、子进程失败只是单次工具结果"的运行时,这仍是值得修的健壮性缺口。

    归属结论:问题在 DSH 本体的 subprocess seam,不在桌面壳。完整证据链、四层进程身份记录与修复建议已更新至官方仓库的讨论(deepseek-ai/deepseek-harness discussion #4713)。

  4. yaojin3616 commented on Aug 27, 2026

    @yaojin3616
    Contributor
  5. added a commit that references this issue on Aug 27, 2026
    c52f450
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions