mirror of
https://github.com/oven-sh/bun
synced 2026-02-12 03:48:56 +00:00
Fix NAPI finalizer segfault when running rspack/rsbuild
Fixes #24552 When NAPI modules (like rspack/rsbuild via SWC) are used in subprocesses, finalizers can be enqueued during garbage collection but may attempt to run after the NapiEnv has started tearing down, causing segmentation faults at address 0x0. The crash occurs because: 1. NAPI objects with finalizers are garbage collected 2. Finalizers are enqueued to run on the next tick 3. The NapiEnv begins cleanup (m_globalObject becomes null/invalid or VM terminates) 4. When the finalizer runs, it dereferences the invalid globalObject pointer The fix: - Add NapiEnv__canRunFinalizer() to check if env, globalObject are valid and VM is not terminating - Call this check in Finalizer.run() before accessing the env - Skip finalizer execution if the env is no longer valid This prevents the segfault while ensuring finalizers run when safe to do so. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2970,4 +2970,10 @@ extern "C" void NapiEnv__deref(napi_env env)
|
||||
env->deref();
|
||||
}
|
||||
|
||||
extern "C" bool NapiEnv__canRunFinalizer(napi_env env)
|
||||
{
|
||||
// Check if the global object is still valid and VM is not terminating
|
||||
return env && env->globalObject() && !env->isVMTerminating();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1366,6 +1366,7 @@ pub export fn napi_internal_suppress_crash_on_abort_if_desired() void {
|
||||
}
|
||||
|
||||
extern fn napi_internal_remove_finalizer(env: napi_env, fun: napi_finalize, hint: ?*anyopaque, data: ?*anyopaque) callconv(.C) void;
|
||||
extern fn NapiEnv__canRunFinalizer(*NapiEnv) bool;
|
||||
|
||||
pub const Finalizer = struct {
|
||||
env: NapiEnv.Ref,
|
||||
@@ -1375,6 +1376,14 @@ pub const Finalizer = struct {
|
||||
|
||||
pub fn run(this: *Finalizer) void {
|
||||
const env = this.env.get();
|
||||
|
||||
// Safety check: Ensure the env is still valid before running the finalizer.
|
||||
// This prevents crashes when finalizers are enqueued but the NapiEnv is being
|
||||
// torn down (e.g., when a subprocess using NAPI modules is terminating).
|
||||
if (!NapiEnv__canRunFinalizer(env)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const handle_scope = NapiHandleScope.open(env, false);
|
||||
defer if (handle_scope) |scope| scope.close(env);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user