@@ -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