Skip to content

install: skip --no-orphans subreaper path for internal git spawns - #33982

Closed
robobun wants to merge 3 commits into
mainfrom
farm/9e6dffa5/install-git-no-orphans
Closed

robobun wants to merge 3 commits into
mainfrom
farm/9e6dffa5/install-git-no-orphans

Conversation

@robobun

@robobun robobun commented Jul 11, 2026 •

Copy link
Copy Markdown
Collaborator

test/cli/install/migration/complex-workspace.test.ts has been flaking near-constantly on the :debian: 13 x64-asan lane (dozens of builds since ~71375, one hard red in 71888) with:

error: git failed with signal 9
error: git failed with signal 9
error: "git clone" for "install-test1" failed
error: InstallFailed cloning repository for install-test1

Cause

scripts/runner.node.mjs sets BUN_FEATURE_FLAG_NO_ORPHANS=1 for every test on ASAN lanes (since #30875), which bunEnv propagates into the bun install the test spawns.

Inside that bun install:

  • Repository::find_commit runs git log via bun_spawn::run -> process::sync::spawn_posix on the main thread (reached from runTasks.rs:1375 and PackageManagerEnqueue.rs:1237).
  • The git clone / git checkout tasks run via the same helper on threadpool workers.

sync::spawn_posix on the watchdog-arming (main) thread with no-orphans enabled:

  1. snapshots the current direct children,
  2. arms PR_SET_CHILD_SUBREAPER,
  3. runs a wait4(-1, WNOHANG) reap loop while waiting on the child,
  4. on return calls kill_subreaper_adoptees(snapshot), which SIGKILLs every direct child not in the snapshot.

That machinery is intended for bun run/bunx, where the script is the only interesting subprocess. When find_commit reaches it, any threadpool git clone forked between steps 1 and 4 is SIGKILLed, and any that exits during step 3 has its status stolen. ASAN slows the threadpool worker's path from "task picked" to "fork" enough to hit this window regularly.

The existing is_arming_thread() guard only covers calls issued from worker threads; it does not cover a main-thread caller running alongside worker-thread children.

Fix

Add sync::Options::no_orphans_reap (default true) and gate the subreaper/pgroup/adoptee-kill path on it in spawn_posix. bun_spawn::run sets it to false: its sole caller is repository::exec, which is a capture-output utility, not the user-script path. bun run/bunx/create/etc. keep the default.

Verification

New test in test/cli/run/no-orphans.test.ts observes the mechanism deterministically rather than the race: it puts a fake git on PATH that records whether each invocation was placed in its own process group (new_process_group = no_orphans in spawn_posix). With BUN_FEATURE_FLAG_NO_ORPHANS=1:

  • before: find_commit's git log reports own (subreaper path armed),
  • after: it reports parent, same as the threadpool steps.
$ USE_SYSTEM_BUN=1 bun test test/cli/run/no-orphans.test.ts -t "internal git"
  marker: "log own\nclone-no-checkout parent"   # fail
$ bun bd test test/cli/run/no-orphans.test.ts -t "internal git"
  marker: "log parent\nclone-no-checkout parent" # pass

Introduced by #30875.


no test proof · iteration 1 · Platform-specific test(s) that do not run on this machine. Deferring to CI, which covers all platforms: test/cli/install/migration/complex-workspace.test.ts test/cli/run/no-orphans.test.ts

bun install's find_commit runs `git log` via bun_spawn::run on the main
thread while git clones/checkouts are live on the install threadpool.
With BUN_FEATURE_FLAG_NO_ORPHANS set (every test on the x64-asan CI
lane), sync::spawn_posix on the main thread arms PR_SET_CHILD_SUBREAPER,
drains wait4(-1), and on return runs kill_subreaper_adoptees, which
SIGKILLs any direct child that was forked after the pre-spawn snapshot.
A threadpool git clone forked in that window dies with:

    error: git failed with signal 9
    error: "git clone" for "install-test1" failed

which surfaced as near-constant flakes of
test/cli/install/migration/complex-workspace.test.ts on 13 x64-asan.

Add sync::Options::no_orphans_reap (default true) and set it false in
bun_spawn::run: that helper is a capture-output utility for
repository::exec, not the bun run/bunx script path the subreaper
cleanup is meant for.
@robobun

robobun commented Jul 11, 2026 •

Copy link
Copy Markdown
Collaborator Author
Updated 7:11 AM PT - Jul 11th, 2026

❌ @robobun, your commit 2458f69 has 2 failures in Build #71926 (All Failures):


🧪   To try this PR locally:

bunx bun-pr 33982

That installs a local version of the PR into your bun-33982 executable, so you can run:

bun-33982 --bun

@coderabbitai

coderabbitai Bot commented Jul 11, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Changes

Orphan Reaping Control

Layer / File(s) Summary
Reaping option and POSIX gating
src/spawn/process.rs
Adds no_orphans_reap to sync options, defaults it to true, and requires it for the POSIX no-orphans path.
Capture helper opt-out and integration test
src/spawn/lib.rs, test/cli/run/no-orphans.test.ts
Disables orphan reaping for run() and verifies internal Git invocations retain the parent process group during bun install.
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: internal git spawns skip the no-orphans subreaper path.
Description check ✅ Passed The description covers the problem, fix, and verification, even though it uses different headings than the template.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/cli/run/no-orphans.test.ts`:
- Around line 1002-1017: Update the marker assertion in the no-orphans test to
include the expected “clone-bare parent” entry alongside the existing
clone-no-checkout marker. Keep the fake Git behavior in the command-case script
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c08c365f-0b9c-423b-870b-414bb99bd49c

📥 Commits

Reviewing files that changed from the base of the PR and between 9657f37 and 20dddd1.

📒 Files selected for processing (3)
  • src/spawn/lib.rs
  • src/spawn/process.rs
  • test/cli/run/no-orphans.test.ts

Comment thread test/cli/run/no-orphans.test.ts
git+file:// matches neither try_https nor try_ssh, so Repository::download
(and its git clone --bare) is never reached for this fixture; the first
git invocation is find_commit's git log. Remove the dead case arm and
document why so the marker expectation reads unambiguously.
@robobun

robobun commented Jul 11, 2026 •

Copy link
Copy Markdown
Collaborator Author

CI status:

  • All 20 :debian: 13 x64-asan test shards passed on both 71921 and 71926. That is the lane where complex-workspace.test.ts was flaking with git failed with signal 9; no flake either run.
  • The only hard reds are unrelated pre-existing issues:
    • :darwin: 14 x64: the existing bun run --no-orphans (perl): fast-exit intermediate case timed out. It has been flaking on this lane across builds 71903/71905/71909/71921 and is the subject of open PR no-orphans(macOS): close the fast-exit-intermediate race with an inherited-fd sentinel #33965. The test added in this PR is Linux-only (skipIf(!isLinux)) and is skipped on that lane.
    • :darwin: 26 aarch64 (71921): runner infra, git clone vendor 'elysia' timed out before any tests ran; same lane failed on 71917/71916/71915/71909/71905.
  • Flaky-but-retried on Windows: napi.test.ts GC timing, dev-and-prod.test.ts, node-http-connect.test.ts, spawn-pipe-leak.test.ts, fetch-backpressure.test.ts, test-repl-close.js. All passed on retry and are unrelated to the Linux-only spawn_posix change here.

Ready for review.

Comment thread src/spawn/process.rs Outdated

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doc-comment feedback from my earlier pass was addressed in 2458f69. I didn't find further issues, but this touches the --no-orphans subreaper/SIGKILL machinery, so worth a human glance at whether a blanket opt-out for bun_spawn::run is the right layer.

Checked: the new no_orphans_reap field defaults to true and is AND-gated, so every other sync::Options construction site (run_command, bunx, create, upgrade, patch, publish, open, ChangedFilesFilter — all via ..Default::default()) keeps unchanged behavior.
Verified bun_spawn::run's sole caller is repository::exec (src/install/repository.rs:376), matching the "sole caller" claim in the comment.
The new test observes pgid deterministically rather than racing; the git+file:// fixture path skipping --bare was already litigated and resolved in-thread.

Extended reasoning...

Overview

Adds a no_orphans_reap: bool field to process::sync::Options (default true), AND-gates the existing no_orphans computation in spawn_posix on it, and sets it to false in bun_spawn::run. Adds a Linux-only test in test/cli/run/no-orphans.test.ts that puts a fake git on PATH and asserts bun install's internal git log invocation is not placed in its own process group under BUN_FEATURE_FLAG_NO_ORPHANS=1.

Security risks

None identified. The change strictly narrows when the subreaper/adoptee-SIGKILL path arms — it can only result in fewer SIGKILLs of child processes, not more. No new external input is parsed; the fake-git test fixture is hermetic (temp dir, PATH prepend, no network).

Level of scrutiny

Medium-high. The diff is small (~20 lines of production code) and structurally conservative — a new option that defaults to the pre-PR behavior, with exactly one caller opting out. However, the surrounding --no-orphans machinery (PR_SET_CHILD_SUBREAPER, wait4(-1) reap loop, kill_subreaper_adoptees) is subtle process-management infrastructure with cross-thread implications, and the fix encodes a design decision: "bun_spawn::run is a capture-output utility, never a user-script runner, so it should never arm the reap path." That's currently true (grep confirms repository::exec is the only caller), but a maintainer familiar with #30875's design should confirm the opt-out belongs on run() rather than, say, threading a flag down from repository::exec specifically or making the subreaper snapshot thread-aware.

Other factors

  • My prior inline comment (doc-comment polarity read as inverted) was addressed in 2458f69; the field doc now correctly leads with "When true (default)…".
  • CodeRabbit's --bare assertion suggestion was correctly rebutted (the git+file:// fixture never reaches Repository::download) and the unreachable case arm was removed in b3fe04d.
  • CI on the previously-flaking x64-asan lane passed all 20 shards per the author's build-71921 report.
  • Grep of all sync::Options { … } construction sites confirms none would change behavior (Rust would fail to compile without ..Default::default(), and the default is true).
  • The only residual concern is architectural (right layer for the opt-out), not a correctness bug in the diff as written.

robobun added a commit that referenced this pull request Jul 24, 2026
BUN_FEATURE_FLAG_NO_ORPHANS=1 (set on ASAN CI lanes) arms a subreaper
around the main-thread git spawn inside bun install that SIGKILLs
concurrent threadpool clone tasks (#33982); with 16 clones in flight
this test hits that window reliably. Strip the flag from the spawned
install's env since the test exercises install task bookkeeping, not
orphan reaping.
robobun added a commit that referenced this pull request Aug 1, 2026
BUN_FEATURE_FLAG_NO_ORPHANS=1 (set on ASAN CI lanes) arms a subreaper
around the main-thread git spawn inside bun install that SIGKILLs
concurrent threadpool clone tasks (#33982); with 16 clones in flight
this test hits that window reliably. Strip the flag from the spawned
install's env since the test exercises install task bookkeeping, not
orphan reaping.
@robobun

robobun commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator Author

Closing as part of a cleanup of stale pull requests. This PR has had no new commits since 2026-07-11, it conflicts with main, and its last CI run failed. This is not a judgment on the fix itself. If the problem still reproduces on a current build, reopen this PR after a rebase or open a new one against main.

@robobun robobun closed this Sep 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant