fix(wrapper): bound child bootstrap handshake with timeout and parent cancellation - #911
Merged
Merged
Conversation
… cancellation (kxn#910) A child that never answers the synthetic initialize request blocked launchCodexChildSession forever: the bootstrap read loops have no deadline and the launch path ignored ctx. Each wedged launch left the session process and its whole child tree resident, and repeated headless launches accumulated them without bound until the cgroup hit its task limit, after which every clone() in the unit failed with EAGAIN (observed in the field as a 13-hour crash loop, 527 coredumps of external commands and the daemon's own Go runtime dying with "fatal error: newosproc"). Wrap all three backend bootstrap call sites (codex, claude, opencode) in runChildBootstrap, which bounds the handshake with wrapperBootstrapTimeout (15s), honours parent cancellation, and cancels the child context on either so the process is killed and its stdout pipe closes, unblocking the bootstrap goroutine. Co-Authored-By: Claude <noreply@anthropic.com>
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.
Closes #910
问题
三个 backend 的 headless bootstrap(codex/claude/opencode)在 synthetic initialize 握手处都是裸
ReadBytes,无 deadline,launch 路径也不响应 ctx 取消。子进程永远不应答时(实测案例:子进程启动链路被文件锁卡死),launch 永久阻塞,会话进程及整棵子进程树滞留;headless pool 持续拉起新实例,进程数无上限堆积,最终顶满 systemd TasksMax(实测 38071),之后该 cgroup 内所有clone()返回 EAGAIN,daemon 自身 Go runtimefatal error: newosproc,故障持续 13 小时直至人工重启。修复
新增
runChildBootstrap统一封装(所有调用点在internal/app/wrapper/):wrapperBootstrapTimeout(15s,常量与wrapperChildWaitTimeout同处)约束握手;正常握手 1s 内完成,15s 已很宽裕;cmd.Wait()仍由调用方错误路径负责,行为不变。三个调用点(codex
app_child_session.go、claudeapp_child_session_claude.go、opencodeapp_child_session_opencode.go)切换到该封装。测试
TestRunChildBootstrapReturnsBootstrappedStdout正常握手透传;TestRunChildBootstrapTimesOutWedgedChild永不应答的子进程在超时后返回错误且子进程被 cancel;TestRunChildBootstrapHonorsParentCancel父 ctx 取消即时生效并 cancel 子进程;go build ./...、go vet、gofmt通过;go test ./internal/app/wrapper/与go test ./...全量通过;scripts/check/no-local-paths.sh通过。