Repository navigation
Description
What version of Bun is running?
1.4.2 (744846f)
What platform is your computer?
Windows x64 (GitHub Actions windows-latest, Windows 10.0.26100), CPU: sse42 popcnt avx avx2 avx512
What steps can reproduce the bug?
I do not have a minimal reproduction. A self-contained attempt (40 test files, each spawning a bun child that serves a named pipe, then connecting, echoing, destroying the socket and killing the child, run with bun test --parallel and no preload) ran 40 clean iterations on both 1.4.2 and 1.4.3-canary.1 on the same runner image.
What does reproduce is one directory of a public repository, looped on a windows-latest runner:
git clone https://github.com/code-yeongyu/oh-my-openagent
cd oh-my-openagent
git checkout f4ec0065cd8e2b623317b16abe56621c0672b694
bun install --frozen-lockfile
for ($i = 1; $i -le 25; $i++) {
bun --config=bunfig.win2.parallel.toml test --parallel --timeout 30000 packages/senpi-task/src/runners/rpc-host
}Each iteration runs 262 tests across 36 files, about 17 s on the runner. On 1.4.3-canary.1+4b02e1031 one of 25 iterations crashed. On 1.4.2 a 25-iteration loop happened to stay clean, but 1.4.2 crashed four times in the full suite these files belong to.
The crash shows up in a large repository suite run as bun test --parallel (about 1,060 files and 7,960 tests in that shard). The crashing worker was started by the coordinator as:
bun.exe test --test-worker --isolate --timeout=30000 --max-concurrency=20 --preload ./test-env.ts --preload ./test-setup.ts --loader .md:text --jsx-runtime=automatic
It reddens roughly one in five or six runs of that shard. A rerun of the same commit usually passes.
What is the expected behavior?
The worker finishes its files, or Bun reports an ordinary test failure.
What do you see instead?
The worker panics, the file it was running is reported as (worker crashed: exit code 3), and the shard fails:
panic(main thread): Segmentation fault at address 0xFFFFFFFF80070006
oh no: Bun has crashed. This indicates a bug in Bun, not your code.
✗ <test file> (worker crashed: exit code 3)
Four occurrences on 1.4.2 in the full suite, plus one on 1.4.3-canary.1 in the loop above, all on the same runner image and all in files of one directory. The worker had been running for 66 to 94 seconds, with RSS 0.34 to 0.39 GB:
Remapped through bun.report/remap, the first three are a GC sweep destroying a cell whose refcounted member is already garbage:
0x1(twice):WTF::ThreadSafeRefCounted<JSC::WatchpointSet>::deref<-HashMap<int, RefPtr<WatchpointSet>>::~HashMap<-JSC::StructureRareData::~StructureRareData<-MarkedBlock::Handle::sweep<-IncrementalSweeper::doWork<-JSRunLoopTimer<-WTFTimer__fire<-VirtualMachine::auto_tick<-test::parallel::runner::WorkerLoop::begin0xFFFFFFFF80070006:WTF::ThreadSafeRefCounted<WTF::MetaAllocatorHandle>::deref<-MacroAssemblerCodeRef::~MacroAssemblerCodeRef<-DFG::JITData::~JITData<-JSC::CodeBlock::~CodeBlock<-MarkedBlock::Handle::sweep<-LocalAllocator::allocateSlowCase<-ModuleProgramCodeBlock::create<-JSModuleRecord::evaluate(the worker was loading the next test file)0x24: frames are only inntdll.dll.0x0on canary:uv__queue_remove<-uv_timer_stop<-uv_timer_start<-eof_timer_start(win/pipe.c:2418) <-uv__pipe_queue_read<-uv__process_pipe_read_req(win/pipe.c:2232) <-uv__process_reqs<-uv_run<-WindowsLoop::tick_with_timeout<-EventLoop::auto_tick<-test::parallel::runner::WorkerLoop::begin. A pipe read completion is processed for a pipe whose timer state is already gone, which looks like the source of the corruption the 1.4.2 sweeps trip over.
Additional information
- The faulting file is where the corruption surfaced, not what caused it. One crash happened while the worker was evaluating a module whose tests are all skipped on Windows, and another file only reads and parses a JSON file. The code that ran earlier in those workers starts real child processes (
node:child_processspawnofbun.exe, piped stdio) and talks to them overnode:netnamed pipes, then destroys the sockets and kills the children. - Possibly related: Windows: bun test segfault sometimes exits 0 with no test report, and sometimes never exits at all #40376 and 1.4.3 canary windows crash | panic(main thread): Segmentation fault at address 0x0 #43857 (Windows use-after-free in the usockets libuv
poll_cb/us_internal_socket_close_rawpath, fix in Reland "usockets(windows): keep a closed poll alive until the outer tick and libuv are done with it" (#39643) #42667), which would corrupt the heap the same way before a later sweep trips over it; and JSC heap corruption still reproduces on 1.4.3-canary: SIGSEGV in the parallel marker and in a Worker (follow-up to #37284) #41857 (JSC heap corruption caught in the marker and sweeper on macOS). - We now run that directory in its own
bun testinvocation and retry it once on a Bun panic, so the crash no longer blocks our CI, but the crash itself is unchanged.
Activity
[-]Windows: bun test v1.4.2 (744846f84) 14x PARALLEL worker segfaults (heap corruption seen in GC sweep, libuv pipe read on canary) in a suite that spawns child processes over pipes[/-][+]Windows: `bun test --parallel` worker segfaults (heap corruption seen in GC sweep, libuv pipe read on canary) in a suite that spawns child processes over pipes[/+]ci(windows): contain the Bun rpc-host worker crash in its own retried…