@@ -86,6 +86,14 @@ typedef int mode_t;
86
86
extern char **environ;
87
87
#endif
88
88
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
+
89
97
namespace node {
90
98
91
99
using v8::Array;
@@ -153,7 +161,7 @@ static double prog_start_time;
153
161
static bool debugger_running;
154
162
static uv_async_t dispatch_debug_messages_async;
155
163
156
- static Isolate* node_isolate = nullptr ;
164
+ static node::atomic< Isolate*> node_isolate;
157
165
static v8::Platform* default_platform;
158
166
159
167
@@ -3389,28 +3397,46 @@ static void EnableDebug(Environment* env) {
3389
3397
}
3390
3398
3391
3399
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
+
3392
3412
// Called from the main thread.
3393
3413
static 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
+
3394
3420
if (debugger_running == false ) {
3395
3421
fprintf (stderr, " Starting debugger agent.\n " );
3396
3422
3397
- HandleScope scope (node_isolate );
3398
- Environment* env = Environment::GetCurrent (node_isolate );
3423
+ HandleScope scope (isolate );
3424
+ Environment* env = Environment::GetCurrent (isolate );
3399
3425
Context::Scope context_scope (env->context ());
3400
3426
3401
3427
StartDebug (env, false );
3402
3428
EnableDebug (env);
3403
3429
}
3404
- Isolate::Scope isolate_scope (node_isolate);
3430
+
3431
+ Isolate::Scope isolate_scope (isolate);
3405
3432
v8::Debug::ProcessDebugMessages ();
3433
+ CHECK_EQ (nullptr , node_isolate.exchange (isolate));
3406
3434
}
3407
3435
3408
3436
3409
3437
#ifdef __POSIX__
3410
3438
static 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 ();
3414
3440
}
3415
3441
3416
3442
@@ -3464,8 +3490,7 @@ static int RegisterDebugSignalHandler() {
3464
3490
3465
3491
#ifdef _WIN32
3466
3492
DWORD WINAPI EnableDebugThreadProc (void * arg) {
3467
- v8::Debug::DebugBreak (*static_cast <Isolate* volatile *>(&node_isolate));
3468
- uv_async_send (&dispatch_debug_messages_async);
3493
+ TryStartDebugger ();
3469
3494
return 0 ;
3470
3495
}
3471
3496
@@ -3986,7 +4011,8 @@ static void StartNodeInstance(void* arg) {
3986
4011
// Fetch a reference to the main isolate, so we have a reference to it
3987
4012
// even when we need it to access it from another (debugger) thread.
3988
4013
if (instance_data->is_main ())
3989
- node_isolate = isolate;
4014
+ CHECK_EQ (nullptr , node_isolate.exchange (isolate));
4015
+
3990
4016
{
3991
4017
Locker locker (isolate);
3992
4018
Isolate::Scope isolate_scope (isolate);
@@ -3996,7 +4022,7 @@ static void StartNodeInstance(void* arg) {
3996
4022
array_buffer_allocator->set_env (env);
3997
4023
Context::Scope context_scope (context);
3998
4024
3999
- node_isolate ->SetAbortOnUncaughtExceptionCallback (
4025
+ isolate ->SetAbortOnUncaughtExceptionCallback (
4000
4026
ShouldAbortOnUncaughtException);
4001
4027
4002
4028
// Start debug agent when argv has --debug
@@ -4047,12 +4073,15 @@ static void StartNodeInstance(void* arg) {
4047
4073
env = nullptr ;
4048
4074
}
4049
4075
4076
+ if (instance_data->is_main ()) {
4077
+ // Synchronize with signal handler, see TryStartDebugger.
4078
+ while (isolate != node_isolate.exchange (nullptr )); // NOLINT
4079
+ }
4080
+
4050
4081
CHECK_NE (isolate, nullptr );
4051
4082
isolate->Dispose ();
4052
4083
isolate = nullptr ;
4053
4084
delete array_buffer_allocator;
4054
- if (instance_data->is_main ())
4055
- node_isolate = nullptr ;
4056
4085
}
4057
4086
4058
4087
int Start (int argc, char ** argv) {
0 commit comments