fix(fetch): remove latent cross-thread UB in FetchTasklet shutdown#30943
fix(fetch): remove latent cross-thread UB in FetchTasklet shutdown#30943DagmawiKK wants to merge 1 commit into
Conversation
…TTP thread (UB fix)
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughThe pull request modifies ChangesFetch Tasklet VM Shutdown Handling
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
What does this PR do?
Removes a latent data race and JSC thread-safety violation in
FetchTasklet::deref_from_threadduring VM shutdown.Currently, if
is_shutting_down()is true,deref_from_threadsynchronously callsFetchTasklet::deinit(this)on the background HTTP thread. This is Undefined Behavior because it destroysjsc::Weakhandles and modifies single-threaded structures (Response::unref(response)mutates aCell<u32>, andreadable_stream_ref.deinit()drops aReadableStream::Strong) off the main JS thread.This branch is currently unreachable dead code because the JS thread leaks its initial reference when the event loop is halted during
process.exit. However, if Bun were to implement graceful shutdown, eager GC for aborted fetches, or clean up the shutdown memory leak, the HTTP thread would become the final reference holder, triggering a guaranteed segfault.The fix replaces the synchronous
deinitcall with an intentional leak (explicit abandonment). If the VM is shutting down, the HTTP thread will simply return and safely abandon the allocation for the OS to reclaim, avoiding the cross-thread UB.How did you verify your code works?
bun bd test test/js/web/fetch/exiting.test.tsruns 500 concurrent fetches with process.exit(0); passes with exit code 0 and no panicFetchTasklet(initial refs,deref_from_threaddrops, JS thread drops inon_progress_update) to confirm this code is currently dead but dangerous.