Skip to content

fix(core): stop bash hanging after process exit - #42756

Open
yyueniao wants to merge 1 commit into
anomalyco:devfrom
yyueniao:dev
Open

fix(core): stop bash hanging after process exit#42756
yyueniao wants to merge 1 commit into
anomalyco:devfrom
yyueniao:dev

Conversation

@yyueniao

@yyueniaoyyueniao commented Aug 15, 2026

Copy link
Copy Markdown

Issue for this PR

Closes#20902
Closes#25038
Closes#28697
Closes#36342
Closes#37838
Closes#42044
Closes#42524

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Process exit should work same as stdio close so either one can finish the bash command.

How did you verify your code works?

Automated tests:

cd packages/core && bun test test/effect/cross-spawn-spawner.test.ts
cd packages/opencode && bun test test/tool/shell.test.ts -t "grandchild"

Manual: cd packages/opencode && bun dev, then run:

node -e 'const {spawn}=require("node:child_process");const c=spawn("sleep",["3600"],{stdio:"inherit",detached:true});c.unref();console.log("done")'

Before: see done, but opencode hang and tool never completes.
After: tool returns immediately.

Screenshots / recordings

N/A

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

Potential related PRs found:

  1. fix(core): resolve child process exit signal on exit event #42275: fix(core): resolve child process exit signal on exit event

    • Related to handling child process exit signals, similar domain to the current PR
  2. fix(core): resolve spawn completion on exit, not only close (Windows detached-child hang) #29831: fix(core): resolve spawn completion on exit, not only close (Windows detached-child hang)

    • Directly related—addresses the same issue of process hanging due to exit vs. close events. This appears to be a previous attempt or related fix for detached child process hangs.

Why they're related: Both PRs address process completion signaling (exit vs. close events) to prevent subprocess hangs, particularly with detached processes. PR #29831 specifically mentions "Windows detached-child hang" which is the same class of issue as what PR #42756 is fixing.

@Enough1122

Copy link
Copy Markdown

AI code review — automated review for reference; please use your judgment.

Scope: the spawner's completion deferred now resolves on whichever of exit/close fires first (previously only close), so a detached grandchild holding stdio open no longer hangs the tool forever. Closes 7 long-standing issues.

  • Correct minimal fix: first-event-wins via the existing end flag, and the close handler still prefers previously recorded exit args (exit ?? args) so the reported code/signal stays consistent.
  • One behavioral edge worth a maintainer look: for normal commands, exit fires before close (stdio flush). Resolving the exit-code deferred on exit is fine as long as every consumer keeps draining stdout/stderr independently after the deferred resolves — if any caller treats deferred completion as "output fully collected", output could be truncated on the happy path. The added test covers the hang case; a regression test asserting full stdout capture on a normal large-output command would close that loop.
  • Test correctly gated to non-Windows (detached-grandchild semantics differ) and cleans up the orphan with SIGKILL.
  • Manual repro in the description matches the mechanism; the seven linked issues all fit this root cause.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment