Skip to content

Microtasks policy incorrect, leading to DCHECK, when calling window.open from setImmediate #29463

@nornagon

Description

@nornagon

To repro, run this fiddle under a debug build: https://gist.github.com/b72948eafa5a2f61acf9f4718ff09259

#
# Fatal error in ../../v8/src/api/api-inl.h, line 183
# Debug check failed: microtask_queue->GetMicrotasksScopeDepth() || !microtask_queue->DebugMicrotasksScopeDepthIsZero().
#
#
#
#FailureMessage Object: 0x7ffeebb54620
0   Electron Framework                  0x000000010c472bb9 base::debug::CollectStackTrace(void**, unsigned long) + 9
1   Electron Framework                  0x000000010c38e243 base::debug::StackTrace::StackTrace() + 19
2   Electron Framework                  0x000000010e820ffd gin::(anonymous namespace)::PrintStackTrace() + 45
3   Electron Framework                  0x000000010e1f7136 V8_Fatal(char const*, int, char const*, ...) + 326
4   Electron Framework                  0x000000010e1f6b15 v8::base::(anonymous namespace)::DefaultDcheckHandler(char const*, int, char const*) + 21
5   Electron Framework                  0x0000000109695f11 v8::CallDepthScope<true>::~CallDepthScope() + 865
6   Electron Framework                  0x0000000109653283 v8::Function::Call(v8::Local<v8::Context>, v8::Local<v8::Value>, int, v8::Local<v8::Value>*) + 835
7   Electron Framework                  0x00000001118657e2 node::InternalMakeCallback(node::Environment*, v8::Local<v8::Object>, v8::Local<v8::Object>, v8::Local<v8::Function>, int, v8::Local<v8::Value>*, node::async_context) + 738
8   Electron Framework                  0x0000000111865aab node::MakeCallback(v8::Isolate*, v8::Local<v8::Object>, v8::Local<v8::Function>, int, v8::Local<v8::Value>*, node::async_context) + 187
9   Electron Framework                  0x00000001118aebf5 node::Environment::CheckImmediate(uv_check_s*) + 181
10  Electron Framework                  0x0000000107c458ad uv__run_check + 157
11  Electron Framework                  0x0000000107c3f7e1 uv_run + 369
12  Electron Framework                  0x0000000107e0964c electron::NodeBindings::UvRunOnce() + 348
13  Electron Framework                  0x0000000107e0ae04 base::internal::Invoker<base::internal::BindState<void (electron::NodeBindings::*)(), base::WeakPtr<electron::NodeBindings> >, void ()>::RunOnce(base::internal::BindStateBase*) + 148
14  Electron Framework                  0x000000010c40a190 base::TaskAnnotator::RunTask(char const*, base::PendingTask*) + 400
15  Electron Framework                  0x000000010c42e292 base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl(base::sequence_manager::LazyNow*) + 994
16  Electron Framework                  0x000000010c42dab8 base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork() + 88
17  Electron Framework                  0x000000010c489d71 base::MessagePumpCFRunLoopBase::RunWork() + 65
18  Electron Framework                  0x000000010c4829a2 base::mac::CallWithEHFrame(void () block_pointer) + 10
19  Electron Framework                  0x000000010c48979f base::MessagePumpCFRunLoopBase::RunWorkSource(void*) + 63
20  CoreFoundation                      0x00007fff2f446832 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
21  CoreFoundation                      0x00007fff2f4467d1 __CFRunLoopDoSource0 + 103
22  CoreFoundation                      0x00007fff2f4465eb __CFRunLoopDoSources0 + 209
23  CoreFoundation                      0x00007fff2f44531a __CFRunLoopRun + 927
24  CoreFoundation                      0x00007fff2f44491e CFRunLoopRunSpecific + 462
25  Foundation                          0x00007fff31ae01a8 -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 212
26  Electron Framework                  0x000000010c48a3ae base::MessagePumpNSRunLoop::DoRun(base::MessagePump::Delegate*) + 126
27  Electron Framework                  0x000000010c48914c base::MessagePumpCFRunLoopBase::Run(base::MessagePump::Delegate*) + 140
28  Electron Framework                  0x000000010c42ee5b base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run(bool, base::TimeDelta) + 651
29  Electron Framework                  0x000000010c3e2d6a base::RunLoop::Run(base::Location const&) + 890
30  Electron Framework                  0x00000001115efc1b content::RendererMain(content::MainFunctionParams const&) + 1611
31  Electron Framework                  0x00000001095d3c27 content::ContentMainRunnerImpl::Run(bool) + 503
32  Electron Framework                  0x00000001095d2b32 content::RunContentProcess(content::ContentMainParams const&, content::ContentMainRunner*) + 2658
33  Electron Framework                  0x00000001095d2c1c content::ContentMain(content::ContentMainParams const&) + 44
34  Electron Framework                  0x0000000107c52297 ElectronMain + 135
35  Electron Helper (Renderer)          0x00000001040ad1b7 main + 439
36  libdyld.dylib                       0x00007fff694e6cc9 start + 1

I believe this is due to the hack in UvRunOnce being insufficient to swap between kExplicit and kScoped microtask policies when a new node environment is created during execution of UvRunOnce. i.e. this:

// Node.js expects `kExplicit` microtasks policy and will run microtasks
// checkpoints after every call into JavaScript. Since we use a different
// policy in the renderer - switch to `kExplicit` and then drop back to the
// previous policy value.
auto old_policy = env->isolate()->GetMicrotasksPolicy();
DCHECK_EQ(v8::MicrotasksScope::GetCurrentDepth(env->isolate()), 0);
env->isolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);

sets the policy to kExplicit, but then CreateEnvironment is called during the tick, and subsequently this:

node::SetIsolateUpForNode(context->GetIsolate(), is);

is called, which sets the policy back to kScoped, due to:

// Match Blink's behavior by allowing microtasks invocation to be controlled
// by MicrotasksScope objects.
is.policy = v8::MicrotasksPolicy::kScoped;

Since the policy is now kScoped, the DCHECK in question triggers the next time a JS function is called, which is in the CheckImmediate code in Node.

cc @codebytere

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions