fix(acp): synchronously reap ACP child to avoid SIGCHLD race#9023
Conversation
Fixes #8373. The `console` crate has a bug in its use of select(): any interruption is treated as a fatal error and propagated. We were killing the ACP child and then immediately proceeding, which set up a race; if the child was reaped after select() started, the SIGCHLD interrupting select() caused the program to exit. Wait for the child to be reaped before proceeding to eliminate the race. Also, use Stdio::inherit() for child stderr to prevent ACP children which output anything on stderr from messing up the CLI.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fa2cc085d1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Signed-off-by: jh-block <jhugo@block.xyz>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 302a3ab83a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Replace BufReader::split-based line splitting with manual chunked reads that flush at MAX_LINE_LEN (8 KiB) bytes. A child emitting \r-terminated progress output or binary data without newlines could otherwise grow a single Vec<u8> indefinitely while we wait for a newline that never arrives. Signed-off-by: jh-block <jhugo@block.xyz>
* main: feat: move goose2 provider catalog behind ACP layer (#9030) fix: use python3 in developer extension instructions for macOS/Linux compatibility (#8784) fix(acp): synchronously reap ACP child to avoid SIGCHLD race (#9023) fix goose2 small-window chat and settings layouts (#9019) docs: improve goose2 AGENTS.md (#9028) agents: add CLAUDE.mds to mirror AGENTS.mds (#9029) remove skill categories (#9008) fix: 8531 - elicitation fixes (#8999) feat(chat): group consecutive tool calls into one summarized chain card (#8995) fix(ci): mark openai/gpt-5 smoke test as flaky (#9027) goose2 distribution bundling (#8911) Add "Trimmed trailing whitespace" message to moim whitelist (#8847)
Pulls 40 new commits from main, including: - #8945 remove artifacts dir handling (lines up with our /artifacts cwd fix) - #9000 replace raw config and secret methods - #9008 remove skill categories - #9019 fix small-window chat & settings layouts - #9023 ACP child reap fix - #8911 goose2 distribution bundling - #8983 SACP session-name notifications - #8985 use ACP session id in goose2 UI - #8995 group consecutive tool calls into chain card - #8996 protocol artifact messages (replace heuristics/regexes) - #8999 elicitation fixes - #9000 plus follow-ups for config/secret ACP methods - many smaller changes across CI workflows, AGENTS docs, deps Conflicts resolved: - src-tauri/src/commands/projects.rs: kept our delete (we moved projects to ACP); main had unrelated edits. - src-tauri/src/lib.rs: dropped projects::* command registrations, kept main's get_goose_serve_host_info addition. - check-file-sizes.mjs: accepted main's deletion (#8996 removed it). - features/projects/api/projects.ts: kept our ACP-based rewrite (ProjectInfo without createdAt/updatedAt; uniqueProjectSlug for collision avoidance). - features/projects/lib/chatProjectContext.ts: took main's rename resolveProjectArtifactRoots → resolveProjectRoots and dropped /artifacts segment append (we already had this fix); dropped buildProjectSystemPrompt (backend's load_project_instructions handles project system prompt injection now). - features/projects/lib/sessionCwdSelection.ts: took main's no-project fallback ['~'] (matches our /artifacts removal in the project branch). - features/chat/hooks/useChatSessionController.ts: took main's 3-arg acpPrepareSession (the personaId/projectId we'd been passing were never read on that call path; newSession sends them via _meta). - ProjectInfo test fixtures: dropped createdAt/updatedAt across CreateProjectDialog.test.tsx and sessionCwdSelection.test.ts. - chatProjectContext.test.ts: dropped buildProjectSystemPrompt test.
Fixes #8373.
Supersedes #8790.
The
consolecrate has a bug in its use of select(): any interruption is treated as a fatal error and propagated. We were killing the ACP child and then immediately proceeding, which set up a race; if the child was reaped after select() started, the SIGCHLD interrupting select() caused the program to exit.Wait for the child to be reaped before proceeding to eliminate the race.
Also, use
Stdio::inherit()for child stderr to prevent ACP children which output anything on stderr from messing up the CLI.Upstream PR fixing the bug in the
consolecrate: console-rs/console#286