@@ -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
@@ -3410,28 +3418,46 @@ static void EnableDebug(Environment* env) {
3410
3418
}
3411
3419
3412
3420
3421
+ // Called from an arbitrary thread.
3422
+ static void TryStartDebugger () {
3423
+ // Call only async signal-safe functions here! Don't retry the exchange,
3424
+ // it will deadlock when the thread is interrupted inside a critical section.
3425
+ if (auto isolate = node_isolate.exchange (nullptr )) {
3426
+ v8::Debug::DebugBreak (isolate);
3427
+ uv_async_send (&dispatch_debug_messages_async);
3428
+ CHECK_EQ (nullptr , node_isolate.exchange (isolate));
3429
+ }
3430
+ }
3431
+
3432
+
3413
3433
// Called from the main thread.
3414
3434
static void DispatchDebugMessagesAsyncCallback (uv_async_t * handle) {
3435
+ // Synchronize with signal handler, see TryStartDebugger.
3436
+ Isolate* isolate;
3437
+ do {
3438
+ isolate = node_isolate.exchange (nullptr );
3439
+ } while (isolate == nullptr );
3440
+
3415
3441
if (debugger_running == false ) {
3416
3442
fprintf (stderr, " Starting debugger agent.\n " );
3417
3443
3418
- HandleScope scope (node_isolate );
3419
- Environment* env = Environment::GetCurrent (node_isolate );
3444
+ HandleScope scope (isolate );
3445
+ Environment* env = Environment::GetCurrent (isolate );
3420
3446
Context::Scope context_scope (env->context ());
3421
3447
3422
3448
StartDebug (env, false );
3423
3449
EnableDebug (env);
3424
3450
}
3425
- Isolate::Scope isolate_scope (node_isolate);
3451
+
3452
+ Isolate::Scope isolate_scope (isolate);
3426
3453
v8::Debug::ProcessDebugMessages ();
3454
+ CHECK_EQ (nullptr , node_isolate.exchange (isolate));
3427
3455
}
3428
3456
3429
3457
3430
3458
#ifdef __POSIX__
3431
3459
static void EnableDebugSignalHandler (int signo) {
3432
- // Call only async signal-safe functions here!
3433
- v8::Debug::DebugBreak (*static_cast <Isolate* volatile *>(&node_isolate));
3434
- uv_async_send (&dispatch_debug_messages_async);
3460
+ TryStartDebugger ();
3435
3461
}
3436
3462
3437
3463
@@ -3485,8 +3511,7 @@ static int RegisterDebugSignalHandler() {
3485
3511
3486
3512
#ifdef _WIN32
3487
3513
DWORD WINAPI EnableDebugThreadProc (void * arg) {
3488
- v8::Debug::DebugBreak (*static_cast <Isolate* volatile *>(&node_isolate));
3489
- uv_async_send (&dispatch_debug_messages_async);
3514
+ TryStartDebugger ();
3490
3515
return 0 ;
3491
3516
}
3492
3517
@@ -4006,7 +4031,8 @@ static void StartNodeInstance(void* arg) {
4006
4031
// Fetch a reference to the main isolate, so we have a reference to it
4007
4032
// even when we need it to access it from another (debugger) thread.
4008
4033
if (instance_data->is_main ())
4009
- node_isolate = isolate;
4034
+ CHECK_EQ (nullptr , node_isolate.exchange (isolate));
4035
+
4010
4036
{
4011
4037
Locker locker (isolate);
4012
4038
Isolate::Scope isolate_scope (isolate);
@@ -4016,7 +4042,7 @@ static void StartNodeInstance(void* arg) {
4016
4042
array_buffer_allocator->set_env (env);
4017
4043
Context::Scope context_scope (context);
4018
4044
4019
- node_isolate ->SetAbortOnUncaughtExceptionCallback (
4045
+ isolate ->SetAbortOnUncaughtExceptionCallback (
4020
4046
ShouldAbortOnUncaughtException);
4021
4047
4022
4048
// Start debug agent when argv has --debug
@@ -4070,12 +4096,15 @@ static void StartNodeInstance(void* arg) {
4070
4096
env = nullptr ;
4071
4097
}
4072
4098
4099
+ if (instance_data->is_main ()) {
4100
+ // Synchronize with signal handler, see TryStartDebugger.
4101
+ while (isolate != node_isolate.exchange (nullptr )); // NOLINT
4102
+ }
4103
+
4073
4104
CHECK_NE (isolate, nullptr );
4074
4105
isolate->Dispose ();
4075
4106
isolate = nullptr ;
4076
4107
delete array_buffer_allocator;
4077
- if (instance_data->is_main ())
4078
- node_isolate = nullptr ;
4079
4108
}
4080
4109
4081
4110
int Start (int argc, char ** argv) {
0 commit comments