fix(shell): prevent double-free during GC finalization#26626
fix(shell): prevent double-free during GC finalization#26626Jarred-Sumner merged 2 commits intomainfrom
Conversation
Fixes #26625 This fixes a segmentation fault that occurred when the GC finalizer tried to free shell interpreter resources that were already partially freed during normal shell completion. The issue happened in this sequence: 1. Shell script completes, `finish()` calls `#derefRootShellAndIOIfNeeded()` which frees root_io and root_shell, then sets `this_jsvalue = .zero` 2. GC runs later and calls `deinitFromFinalizer()`, which called `#derefRootShellAndIOIfNeeded()` again 3. The guard `if (this_jsvalue != .zero)` was unreliable for preventing double-free in all scenarios The fix adds an explicit `cleanup_state` enum to track resource ownership: - `needs_full_cleanup`: Nothing cleaned up yet, finalizer must clean everything - `runtime_cleaned`: finish() already cleaned IO/shell, finalizer skips those This was reported on Windows x64 with high GC pressure (many concurrent shell commands), but the vulnerability existed on all platforms. Co-Authored-By: Claude Opus 4.5 <[email protected]>
|
Updated 6:21 PM PT - Jan 31st, 2026
❌ @Jarred-Sumner, your commit 19b5a3f has 1 failures in
🧪 To try this PR locally: bunx bun-pr 26626That installs a local version of the PR into your bun-26626 --bun |
WalkthroughThe changes add a cleanup state tracking mechanism to the shell interpreter to prevent double-free crashes during garbage collection finalization. A new Changes
Possibly related PRs
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
|
I've tried running the build from this PR on Windows three times: it crashed the first time, worked normally the second time, and crashed again the third time. |
Summary
Fixes #26625
This fixes a segmentation fault that occurred on Windows x64 when the GC finalizer tried to free shell interpreter resources that were already partially freed during normal shell completion.
cleanup_stateenum to track resource ownership stateneeds_full_cleanup: Nothing cleaned up yet, finalizer must clean everythingruntime_cleaned:finish()already cleaned IO/shell, finalizer skips those#derefRootShellAndIOIfNeeded()when already cleaneddeinitFromFinalizer()The vulnerability existed on all platforms but was most reliably triggered on Windows with high GC pressure (many concurrent shell commands).
Test plan
bun bd)test/regression/issue/26625.test.ts)🤖 Generated with Claude Code