@@ -86,6 +86,14 @@ typedef int mode_t;
8686extern char **environ;
8787#endif
8888
89+ #ifdef __APPLE__
90+ #include " atomic-polyfill.h" // NOLINT(build/include_order)
91+ namespace node { template <typename T> using atomic = nonstd::atomic<T>; }
92+ #else
93+ #include < atomic>
94+ namespace node { template <typename T> using atomic = std::atomic<T>; }
95+ #endif
96+
8997namespace node {
9098
9199using v8::Array;
@@ -153,7 +161,7 @@ static double prog_start_time;
153161static bool debugger_running;
154162static uv_async_t dispatch_debug_messages_async;
155163
156- static Isolate* node_isolate = nullptr ;
164+ static node::atomic< Isolate*> node_isolate;
157165static v8::Platform* default_platform;
158166
159167
@@ -3389,28 +3397,46 @@ static void EnableDebug(Environment* env) {
33893397}
33903398
33913399
3400+ // Called from an arbitrary thread.
3401+ static void TryStartDebugger () {
3402+ // Call only async signal-safe functions here! Don't retry the exchange,
3403+ // it will deadlock when the thread is interrupted inside a critical section.
3404+ if (auto isolate = node_isolate.exchange (nullptr )) {
3405+ v8::Debug::DebugBreak (isolate);
3406+ uv_async_send (&dispatch_debug_messages_async);
3407+ CHECK_EQ (nullptr , node_isolate.exchange (isolate));
3408+ }
3409+ }
3410+
3411+
33923412// Called from the main thread.
33933413static void DispatchDebugMessagesAsyncCallback (uv_async_t * handle) {
3414+ // Synchronize with signal handler, see TryStartDebugger.
3415+ Isolate* isolate;
3416+ do {
3417+ isolate = node_isolate.exchange (nullptr );
3418+ } while (isolate == nullptr );
3419+
33943420 if (debugger_running == false ) {
33953421 fprintf (stderr, " Starting debugger agent.\n " );
33963422
3397- HandleScope scope (node_isolate );
3398- Environment* env = Environment::GetCurrent (node_isolate );
3423+ HandleScope scope (isolate );
3424+ Environment* env = Environment::GetCurrent (isolate );
33993425 Context::Scope context_scope (env->context ());
34003426
34013427 StartDebug (env, false );
34023428 EnableDebug (env);
34033429 }
3404- Isolate::Scope isolate_scope (node_isolate);
3430+
3431+ Isolate::Scope isolate_scope (isolate);
34053432 v8::Debug::ProcessDebugMessages ();
3433+ CHECK_EQ (nullptr , node_isolate.exchange (isolate));
34063434}
34073435
34083436
34093437#ifdef __POSIX__
34103438static void EnableDebugSignalHandler (int signo) {
3411- // Call only async signal-safe functions here!
3412- v8::Debug::DebugBreak (*static_cast <Isolate* volatile *>(&node_isolate));
3413- uv_async_send (&dispatch_debug_messages_async);
3439+ TryStartDebugger ();
34143440}
34153441
34163442
@@ -3464,8 +3490,7 @@ static int RegisterDebugSignalHandler() {
34643490
34653491#ifdef _WIN32
34663492DWORD WINAPI EnableDebugThreadProc (void * arg) {
3467- v8::Debug::DebugBreak (*static_cast <Isolate* volatile *>(&node_isolate));
3468- uv_async_send (&dispatch_debug_messages_async);
3493+ TryStartDebugger ();
34693494 return 0 ;
34703495}
34713496
@@ -3986,7 +4011,8 @@ static void StartNodeInstance(void* arg) {
39864011 // Fetch a reference to the main isolate, so we have a reference to it
39874012 // even when we need it to access it from another (debugger) thread.
39884013 if (instance_data->is_main ())
3989- node_isolate = isolate;
4014+ CHECK_EQ (nullptr , node_isolate.exchange (isolate));
4015+
39904016 {
39914017 Locker locker (isolate);
39924018 Isolate::Scope isolate_scope (isolate);
@@ -3996,7 +4022,7 @@ static void StartNodeInstance(void* arg) {
39964022 array_buffer_allocator->set_env (env);
39974023 Context::Scope context_scope (context);
39984024
3999- node_isolate ->SetAbortOnUncaughtExceptionCallback (
4025+ isolate ->SetAbortOnUncaughtExceptionCallback (
40004026 ShouldAbortOnUncaughtException);
40014027
40024028 // Start debug agent when argv has --debug
@@ -4047,12 +4073,15 @@ static void StartNodeInstance(void* arg) {
40474073 env = nullptr ;
40484074 }
40494075
4076+ if (instance_data->is_main ()) {
4077+ // Synchronize with signal handler, see TryStartDebugger.
4078+ while (isolate != node_isolate.exchange (nullptr )); // NOLINT
4079+ }
4080+
40504081 CHECK_NE (isolate, nullptr );
40514082 isolate->Dispose ();
40524083 isolate = nullptr ;
40534084 delete array_buffer_allocator;
4054- if (instance_data->is_main ())
4055- node_isolate = nullptr ;
40564085}
40574086
40584087int Start (int argc, char ** argv) {
0 commit comments