Repository navigation
Conversation
…nkey2jack#9) claude/codex runs could freeze a chat slot for hours when the CLI exited fast without a terminal event: a grandchild inheriting the stdout write handle kept the readline alive, so the event stream never ended and the idle watchdog's stop() was a no-op on an already-dead child (2026-11-08 incident, issue monkey2jack#9). - adapters: unconditional stdout destroy 2s after child exit (was: only when nothing had been printed); synthesize an error event when claude exits without a result event - adapters: stop() now escalates to a process-tree kill (taskkill /T /F on Windows — child.kill() cannot reach past the .cmd shim); new AgentRun.forceKillTree() works even after the child exited - executor: EventFanout.abort() ends a wedged stream with a synthetic terminal error; execution.forceClose() = abort + tree kill, wired to the watchdog firing 10s after stop() failed to end the run - executor: previous-exit-timeout now tree-kills the stuck run instead of leaking it as an orphan holding its session file open - channel: watchdog escalation logs at error level with the reason - process-tree kill in src/platform/kill-tree.ts, shared by all three agents (hermes included for the interface); POSIX keeps plain SIGKILL Tests: quick-exit-with-grandchild coverage for claude and codex (stream ends <7s with a terminal error), forceClose hard-exit and drain-timeout tree-kill unit tests, a real taskkill /T /F tree test on Windows. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
monkey2jack
added a commit
that referenced
this pull request
Nov 13, 2026
Restore stuck streams after the agent process exits, preserve buffered output and retry watchdog recovery without prematurely releasing a running process. Synchronize the Chinese README banner. Based on issue #9 and PR #10 by @alone-lon. Windows descendant process cleanup remains to be investigated.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
修复 #9(2026-11-08 claude run 假死:子进程快速退出后事件流挂死,看门狗无法闭环)。claude.exe 偶发在产出终态事件前快速退出,而它的孙进程继承了 stdout 写句柄——事件流的 readline 永远等不到 EOF,
for await永久挂起;此时 idle-watchdog 调的stop()对已死进程是空操作,inflight 槽位冻结,该 chat 所有新消息只能排队,只能重启恢复。三层修复,与 issue 里的 P0/P1/P2 一一对应:
exit,无条件宽限 2 秒(留尾行 flush)后 destroy stdout 强制 EOF,走已有的 exitCode→yield error路径。原兜底closeSilentStdout只在!sawStdout时生效,正常 run 的 init 行早已输出,形同虚设。另外 claude 退出码 0 但从未产出result事件时补发合成 error,保证任何情况下事件流必出终态(codex 原有translator.finish()兜底不受影响)。EventFanout新增abort(),能打断卡死的 pump(race 掉 pending 的next()),注入合成 error 终态;execution.forceClose()= abort + 杀进程树。看门狗开火 10 秒后 run 仍未到终态即触发,error 级日志留证据。原则:任何 run 必须存在一条与事件流是否配合无关的强制出口。src/platform/kill-tree.ts(Windowstaskkill /T /F——child.kill()杀不到.cmdshim 后面的真身和孙进程;POSIX 保持 SIGKILL)。接入三处:adapterstop()宽限到期、executorwaitForPreviousExit超时分支(原来只删 map 不杀进程——issue 里那个悬空两小时的孤儿就是这么来的)、forceClose。AgentRun接口新增pid与forceKillTree();hermes adapter 同步实现接口(行为不变)。P3 观测随 P1 落地(stdout-force-close-after-exit、watchdog-force-close、previous-exit-timeout均有日志)。Test plan
taskkill /T /F树杀测试(父+孙进程全灭)pnpm typecheck、pnpm build通过备注
holdEmptyDone,与本次pid字段已合并、测试全绿)🤖 Generated with Claude Code