From 52c644966d78503d63fca3b50b041bce429c8c84 Mon Sep 17 00:00:00 2001 From: Chengzhong Wu Date: Tue, 7 Jan 2025 11:03:55 +0000 Subject: [PATCH] src: drain platform tasks before creating startup snapshot Drain the loop and platform tasks before creating a snapshot. This is necessary to ensure that the no roots are held by the the platform tasks, which may reference objects associated with a context. For example, a WeakRef may schedule an per-isolate platform task as a GC root, and referencing an object in a context, causing an assertion in the snapshot creator. PR-URL: https://github.com/nodejs/node/pull/56403 Refs: https://github.com/nodejs/node/pull/56292 Reviewed-By: James M Snell Reviewed-By: Joyee Cheung --- src/node_snapshotable.cc | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/node_snapshotable.cc b/src/node_snapshotable.cc index fe04a8ee8d7..fe3fcc71842 100644 --- a/src/node_snapshotable.cc +++ b/src/node_snapshotable.cc @@ -973,25 +973,29 @@ ExitCode BuildSnapshotWithoutCodeCache( } }); + Context::Scope context_scope(setup->context()); + Environment* env = setup->env(); + // Run the custom main script for fully customized snapshots. if (snapshot_type == SnapshotMetadata::Type::kFullyCustomized) { - Context::Scope context_scope(setup->context()); - Environment* env = setup->env(); #if HAVE_INSPECTOR env->InitializeInspector({}); #endif if (LoadEnvironment(env, builder_script_content.value()).IsEmpty()) { return ExitCode::kGenericUserError; } + } - // FIXME(joyeecheung): right now running the loop in the snapshot - // builder might introduce inconsistencies in JS land that need to - // be synchronized again after snapshot restoration. - ExitCode exit_code = - SpinEventLoopInternal(env).FromMaybe(ExitCode::kGenericUserError); - if (exit_code != ExitCode::kNoFailure) { - return exit_code; - } + // Drain the loop and platform tasks before creating a snapshot. This is + // necessary to ensure that the no roots are held by the the platform + // tasks, which may reference objects associated with a context. For + // example, a WeakRef may schedule an per-isolate platform task as a GC + // root, and referencing an object in a context, causing an assertion in + // the snapshot creator. + ExitCode exit_code = + SpinEventLoopInternal(env).FromMaybe(ExitCode::kGenericUserError); + if (exit_code != ExitCode::kNoFailure) { + return exit_code; } }