DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

Deno child.kill 发送 STOP 后不能 CONT,区分信号已发送与进程已退出

Deno 曾把 ChildProcess.killed 当成终止标记,成功发送一次信号后拒绝 CONT 等后续信号。2.9.7 修正发送状态与实际退出的区别,并保持通道生命周期。

在 Deno 的 node:child_process 中先发送 SIGSTOP,再发送 SIGCONT,后一个调用返回 false,子进程一直停着,可以检查 ChildProcess.killed 是否被误当成已经退出。

原 Linux、Deno 2.9.5 组合中,暂停子进程后继续信号没有真正发出。killed 只记录曾成功发送过信号,并不说明目标已经终止;SIGSTOP 本来就不会结束进程。旧实现却在这个标记为 true 后拒绝后续 kill(),还提前收尾标准输入和 IPC。

保留实际子进程对象,在受控 POSIX 环境观察两次调用:

console.log(child.kill('SIGSTOP'));
console.log({ sentBefore: child.killed });
console.log(child.kill('SIGCONT'));

child 必须是测试真正创建并已经就绪的子进程。此片段不是任意现存 PID 的探针,也不适合 Windows 的信号能力;测试要保留收尾逻辑,避免让暂停进程长期残留。

Deno 2.9.7 包含对应状态处理:进程 handle 仍可用时尝试发送后续信号,stdio 与 IPC 按真实进程或通道终止情况收尾。更新后,不要把 killed === true 作为跳过继续或强制终止的唯一判断,也不要因为 kill() 返回 true 就声称子进程已经退出。

验收可以启动一个会响应标准输入并回传结果的子进程,等待 ready,再发 STOP、CONT,之后写入一条探针消息。两次信号应成功提交,恢复后的子进程应回传数据;最后按测试设计终止它,并等待退出或关闭事件。仅第二次返回 true,还不足以证明旧的 IPC 提前断开问题没有残留。

应用的优雅退出也可能先发送 SIGTERM,到截止时间仍未退出再发 SIGKILL。这里修补的是后一次请求不应仅因前一次成功发送而被禁止,具体截止时间与业务收尾仍由应用决定。

不要用“再调用一次 spawn”代替恢复,原进程的资源与任务状态可能仍存在。这也不同于 shell 没把信号传给下游、杀进程树遗漏后代或父进程等待 pipe 结束;那些路径需要各自检查,更新这一状态标记不会自动处理所有进程协调问题。