deepak1556

#49090: fix: crash when attempting to resolve modules during process exit

Merged
Created: Nov 26, 2025, 5:29:52 AM
Merged: Nov 27, 2025, 3:30:10 AM
4 comments
Target: main

Description of Change

Refs microsoft/vscode#256031

_Analysis based on crash dumps_

Only listing the interesting threads below

Crashed Thread:        12

Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000

Termination Reason:    Namespace SIGNAL, Code 6 Abort trap: 6
Terminating Process:   Electron [56936]

Application Specific Information:
abort() called


Thread 0::  Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib        	       0x190fe39b8 __ulock_wait + 8
1   libsystem_pthread.dylib       	       0x19102606c _pthread_join + 608
2   Electron Framework            	       0x119600a5c uv_thread_join + 20
3   Electron Framework            	       0x119a1b2ac node::worker::Worker::JoinThread() + 60
4   Electron Framework            	       0x11988d5b4 node::Environment::stop_sub_worker_contexts() + 216
5   Electron Framework            	       0x119827460 node::DefaultProcessExitHandler(node::Environment*, int) + 44
6   Electron Framework            	       0x11988d4c0 node::Environment::Exit(node::ExitCode) + 412
7   ???                           	       0x138d90278 ???
8   ???                           	       0x138d8e270 ???
9   ???                           	       0x138d8e270 ???
10  ???                           	       0x1310e7734 ???
11  ???                           	       0x1310f8b7c ???
12  ???                           	       0x138d8b228 ???
13  ???                           	       0x138d8ae74 ???
14  Electron Framework            	       0x1172db5cc v8::Function::Call(v8::Isolate*, v8::Local<v8::Context>, v8::Local<v8::Value>, int, v8::Local<v8::Value>*) + 3576
15  Electron Framework            	       0x1172da968 v8::Function::Call(v8::Isolate*, v8::Local<v8::Context>, v8::Local<v8::Value>, int, v8::Local<v8::Value>*) + 404
16  Electron Framework            	       0x11988bf20 node::Environment::RunTimers(uv_timer_s*) + 356
17  Electron Framework            	       0x1195f0ea0 uv__run_timers + 144
18  Electron Framework            	       0x1195f4320 uv_run + 600
19  Electron Framework            	       0x119821b64 node::SpinEventLoopInternal(node::Environment*) + 360
20  Electron Framework            	       0x119822a60 node::SpinEventLoop(node::Environment*) + 12
21  Electron Framework            	       0x11960ad38 ElectronInitializeICUandStartNode + 17784
22  Electron Framework            	       0x1196068cc ElectronInitializeICUandStartNode + 268
23  dyld                          	       0x190c82b98 start + 6076

...

Thread 12 Crashed:
0   libsystem_kernel.dylib        	       0x190fea388 __pthread_kill + 8
1   libsystem_pthread.dylib       	       0x191023848 pthread_kill + 296
2   libsystem_c.dylib             	       0x190f2c9e4 abort + 124
3   Electron Framework            	       0x11990195c node::OnFatalError(char const*, char const*) + 252
4   Electron Framework            	       0x11a5f9318 v8::PropertyDescriptor::set() const + 4540844
5   Electron Framework            	       0x11995ec20 node::modules::BindingData::GetPackageJSON(node::Realm*, std::__Cr::basic_string_view<char, std::__Cr::char_traits<char>>, node::modules::BindingData::ErrorContext*) + 5712
6   Electron Framework            	       0x119961b54 void node::modules::BindingData::GetPackageScopeConfig<false>(v8::FunctionCallbackInfo<v8::Value> const&) + 1604
7   ???                           	       0x138d90278 ???
8   ???                           	       0x138d8e270 ???
9   ???                           	       0x138d8e270 ???
10  ???                           	       0x131054f88 ???
11  ???                           	       0x138d8e270 ???
12  ???                           	       0x138d8e270 ???
13  ???                           	       0x138d8e270 ???
14  ???                           	       0x131054cb4 ???
15  ???                           	       0x131053dfc ???
16  ???                           	       0x13104ee74 ???
17  ???                           	       0x131059d64 ???
18  ???                           	       0x13104ee74 ???
19  ???                           	       0x131052d74 ???
20  ???                           	       0x131051b54 ???
21  ???                           	       0x131048f1c ???
22  ???                           	       0x138d8e270 ???
23  ???                           	       0x138d8b228 ???
24  ???                           	       0x138d8ae74 ???
25  Electron Framework            	       0x1172db5cc v8::Function::Call(v8::Isolate*, v8::Local<v8::Context>, v8::Local<v8::Value>, int, v8::Local<v8::Value>*) + 3576
26  Electron Framework            	       0x1172da968 v8::Function::Call(v8::Isolate*, v8::Local<v8::Context>, v8::Local<v8::Value>, int, v8::Local<v8::Value>*) + 404
27  Electron Framework            	       0x11982115c node::InternalMakeCallback(node::Environment*, v8::Local<v8::Object>, v8::Local<v8::Object>, v8::Local<v8::Function>, int, v8::Local<v8::Value>*, node::async_context, v8::Local<v8::Value>) + 504
28  Electron Framework            	       0x11983002c node::AsyncWrap::MakeCallback(v8::Local<v8::Function>, int, v8::Local<v8::Value>*) + 240
29  Electron Framework            	       0x1199550ec node::worker::MessagePort::OnMessage(node::worker::MessagePort::MessageProcessingMode) + 800
30  Electron Framework            	       0x1195f3d74 uv__async_fork + 772
31  Electron Framework            	       0x119606030 uv__io_poll + 1336
32  Electron Framework            	       0x1195f4240 uv_run + 376
33  Electron Framework            	       0x119821b64 node::SpinEventLoopInternal(node::Environment*) + 360
34  Electron Framework            	       0x119a1afb0 node::worker::Worker::Run() + 2008
35  Electron Framework            	       0x119a1fa14 _register_external_reference_worker(node::ExternalReferenceRegistry*) + 4712
36  libsystem_pthread.dylib       	       0x191023bc8 _pthread_start + 136
37  libsystem_pthread.dylib       	       0x19101eb80 thread_start + 8

(lldb) frame select 5
frame #5: 0x000000010d377c80 Electron Framework`node::modules::BindingData::GetPackageJSON(node::Realm*, std::__Cr::basic_string_view<char, std::__Cr::char_traits<char>>, node::modules::BindingData::ErrorContext*) at v8-local-handle.h:770
General Purpose Registers:
        x8 = 0x0000000000020019
       x19 = 0x0000011800091598
       x20 = 0x0000011800091560
       x21 = 0x0000011800a7dff0
       x22 = 0x0000011800a7dff0
       x23 = 0x0000011800a7c060
       x24 = 0x0000011800ae0000
       x25 = 0x0000011800121f80
       x26 = 0x0000000173bd87e0
       x27 = 0x0000000173bd8858
       x28 = 0x0000000000000064
        fp = 0x0000000173bd8d10
        lr = 0x000000010d377c80  Electron Framework`node::modules::BindingData::GetPackageJSON(node::Realm*, std::__Cr::basic_string_view<char, std::__Cr::char_traits<char>>, node::modules::BindingData::ErrorContext*) + 5852 at v8-local-handle.h
        sp = 0x0000000173bd8720
        pc = 0x000000010d377c80  Electron Framework`node::modules::BindingData::GetPackageJSON(node::Realm*, std::__Cr::basic_string_view<char, std::__Cr::char_traits<char>>, node::modules::BindingData::ErrorContext*) + 5852 at v8-local-handle.h
(lldb) disassemble
...
    0x10d37683c <+664>:  bl     0x10b07ad08    ; v8::Function::Call(v8::Local<v8::Context>, v8::Local<v8::Value>, int, v8::Local<v8::Value>*) at api.cc:5384
    0x10d376840 <+668>:  mov    x22, x0
    0x10d376844 <+672>:  cbz    x0, 0x10d377c7c ; <+5848> at v8-local-handle.h:770
    ...
    0x10d377c7c <+5848>: bl     0x10dede2c4    ; v8::api_internal::ToLocalEmpty() at api.h:217
->  0x10d377c80 <+5852>: b      0x10d376848    ; <+676> at v8-internal.h:1787

We are attempting to resolve an empty handle returned by modules_read_file_sync->Call that leads to the Api failure check. As to why this happens, with a try catch scope added

(v8::TryCatch) try_catch = {
  i_isolate_ = 0x0000011800ac0000
  next_ = nullptr
  exception_ = 0x000009e000020019
  message_obj_ = 0x000009e000020001
  js_stack_comparable_address_ = 6236767984
  is_verbose_ = false
  can_continue_ = false
  capture_message_ = true
  rethrow_ = false
}
(lldb) command script import src/v8/tools/lldb_commands.py
(lldb) job 0x000009e000020001
0x09e000020001 <the_hole_value>
(lldb) job 0x000009e000020019
0x09e000020019 <termination_exception>

We got a termination exception from V8 when the function call was executed that results in the empty handle for result, thread 0 shows we are in the shutdown phase which calls isolate->TerminateExecution when the worker threads are stopped setting thread local interrupt flags. The interrupt handler from the worker thread raises the exception when attempting to enter JS.

The change in this PR makes the JS re-entrancy resilient to this exception. cc @indutny-signal

However, the stop call from the Worker::Exit is ignoring the flags we would ideally be calling for main thread of all our processes, ex:

node::Stop(env, node::StopFlags::kDoNotTerminateIsolate);
. This should be addressed in a followup PR (possibly missed case in nodejs/node#46583) cc @codebytere

Release Notes

Notes: fix crash when attempting to resolve modules during process exit

Backports

39-x-y
Pending
Waiting for a manual backport
40-x-y
Merged
PR Number
#49104
Merged At
Nov 27, 2025, 11:12:32 AM
Released In
v40.0.0-beta.1
Release Date
Dec 1, 2025, 6:18:54 PM

Semver Impact

Major
Breaking changes
Minor
New features
Patch
Bug fixes
None
Docs, tests, etc.

Semantic Versioning helps users understand the impact of updates:

  • Major (X.y.z): Breaking changes that may require code modifications
  • Minor (x.Y.z): New features that maintain backward compatibility
  • Patch (x.y.Z): Bug fixes that don't change the API
  • None: Changes that don't affect using facing parts of Electron