| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 8557597 commit db2b23f
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -73,6 +73,7 @@ | |||
| 73 | 73 | #define umask _umask | |
| 74 | 74 | typedef int mode_t; | |
| 75 | 75 | #else | |
| 76 | + #include <pthread.h> | ||
| 76 | 77 | #include <sys/resource.h> // getrlimit, setrlimit | |
| 77 | 78 | #include <unistd.h> // setuid, getuid | |
| 78 | 79 | #endif | |
@@ -89,14 +90,6 @@ typedef int mode_t; | |||
| 89 | 90 | extern char **environ; | |
| 90 | 91 | #endif | |
| 91 | 92 | ||
| 92 | - #ifdef __APPLE__ | ||
| 93 | - #include "atomic-polyfill.h" // NOLINT(build/include_order) | ||
| 94 | - namespace node { template <typename T> using atomic = nonstd::atomic<T>; } | ||
| 95 | - #else | ||
| 96 | - #include <atomic> | ||
| 97 | - namespace node { template <typename T> using atomic = std::atomic<T>; } | ||
| 98 | - #endif | ||
| 99 | - | ||
| 100 | 93 | namespace node { | |
| 101 | 94 | ||
| 102 | 95 | using v8::Array; | |
@@ -166,9 +159,13 @@ static double prog_start_time; | |||
| 166 | 159 | static bool debugger_running; | |
| 167 | 160 | static uv_async_t dispatch_debug_messages_async; | |
| 168 | 161 | ||
| 169 | - static node::atomic<Isolate*> node_isolate; | ||
| 162 | + static uv_mutex_t node_isolate_mutex; | ||
| 163 | + static v8::Isolate* node_isolate; | ||
| 170 | 164 | static v8::Platform* default_platform; | |
| 171 | 165 | ||
| 166 | + #ifdef __POSIX__ | ||
| 167 | + static uv_sem_t debug_semaphore; | ||
| 168 | + #endif | ||
| 172 | 169 | ||
| 173 | 170 | static void PrintErrorString(const char* format, ...) { | |
| 174 | 171 | va_list ap; | |
@@ -3538,44 +3535,40 @@ static void EnableDebug(Environment* env) { | |||
| 3538 | 3535 | ||
| 3539 | 3536 | // Called from an arbitrary thread. | |
| 3540 | 3537 | static void TryStartDebugger() { | |
| 3541 | - // Call only async signal-safe functions here! Don't retry the exchange, | ||
| 3542 | - // it will deadlock when the thread is interrupted inside a critical section. | ||
| 3543 | - if (auto isolate = node_isolate.exchange(nullptr)) { | ||
| 3538 | + uv_mutex_lock(&node_isolate_mutex); | ||
| 3539 | + if (auto isolate = node_isolate) { | ||
| 3544 | 3540 | v8::Debug::DebugBreak(isolate); | |
| 3545 | 3541 | uv_async_send(&dispatch_debug_messages_async); | |
| 3546 | - CHECK_EQ(nullptr, node_isolate.exchange(isolate)); | ||
| 3547 | 3542 | } | |
| 3543 | + uv_mutex_unlock(&node_isolate_mutex); | ||
| 3548 | 3544 | } | |
| 3549 | 3545 | ||
| 3550 | 3546 | ||
| 3551 | 3547 | // Called from the main thread. | |
| 3552 | 3548 | static void DispatchDebugMessagesAsyncCallback(uv_async_t* handle) { | |
| 3553 | - // Synchronize with signal handler, see TryStartDebugger. | ||
| 3554 | - Isolate* isolate; | ||
| 3555 | - do { | ||
| 3556 | - isolate = node_isolate.exchange(nullptr); | ||
| 3557 | - } while (isolate == nullptr); | ||
| 3549 | + uv_mutex_lock(&node_isolate_mutex); | ||
| 3550 | + if (auto isolate = node_isolate) { | ||
| 3551 | + if (debugger_running == false) { | ||
| 3552 | + fprintf(stderr, "Starting debugger agent.\n"); | ||
| 3558 | 3553 | ||
| 3559 | - if (debugger_running == false) { | ||
| 3560 | - fprintf(stderr, "Starting debugger agent.\n"); | ||
| 3554 | + HandleScope scope(isolate); | ||
| 3555 | + Environment* env = Environment::GetCurrent(isolate); | ||
| 3556 | + Context::Scope context_scope(env->context()); | ||
| 3561 | 3557 | ||
| 3562 | - HandleScope scope(isolate); | ||
| 3563 | - Environment* env = Environment::GetCurrent(isolate); | ||
| 3564 | - Context::Scope context_scope(env->context()); | ||
| 3558 | + StartDebug(env, false); | ||
| 3559 | + EnableDebug(env); | ||
| 3560 | + } | ||
| 3565 | 3561 | ||
| 3566 | - StartDebug(env, false); | ||
| 3567 | - EnableDebug(env); | ||
| 3562 | + Isolate::Scope isolate_scope(isolate); | ||
| 3563 | + v8::Debug::ProcessDebugMessages(); | ||
| 3568 | 3564 | } | |
| 3569 | - | ||
| 3570 | - Isolate::Scope isolate_scope(isolate); | ||
| 3571 | - v8::Debug::ProcessDebugMessages(); | ||
| 3572 | - CHECK_EQ(nullptr, node_isolate.exchange(isolate)); | ||
| 3565 | + uv_mutex_unlock(&node_isolate_mutex); | ||
| 3573 | 3566 | } | |
| 3574 | 3567 | ||
| 3575 | 3568 | ||
| 3576 | 3569 | #ifdef __POSIX__ | |
| 3577 | 3570 | static void EnableDebugSignalHandler(int signo) { | |
| 3578 | - TryStartDebugger(); | ||
| 3571 | + uv_sem_post(&debug_semaphore); | ||
| 3579 | 3572 | } | |
| 3580 | 3573 | ||
| 3581 | 3574 | ||
@@ -3614,11 +3607,46 @@ void DebugProcess(const FunctionCallbackInfo<Value>& args) { | |||
| 3614 | 3607 | } | |
| 3615 | 3608 | ||
| 3616 | 3609 | ||
| 3610 | + inline void* DebugSignalThreadMain(void* unused) { | ||
| 3611 | + for (;;) { | ||
| 3612 | + uv_sem_wait(&debug_semaphore); | ||
| 3613 | + TryStartDebugger(); | ||
| 3614 | + } | ||
| 3615 | + return nullptr; | ||
| 3616 | + } | ||
| 3617 | + | ||
| 3618 | + | ||
| 3617 | 3619 | static int RegisterDebugSignalHandler() { | |
| 3618 | - // FIXME(bnoordhuis) Should be per-isolate or per-context, not global. | ||
| 3620 | + // Start a watchdog thread for calling v8::Debug::DebugBreak() because | ||
| 3621 | + // it's not safe to call directly from the signal handler, it can | ||
| 3622 | + // deadlock with the thread it interrupts. | ||
| 3623 | + CHECK_EQ(0, uv_sem_init(&debug_semaphore, 0)); | ||
| 3624 | + pthread_attr_t attr; | ||
| 3625 | + CHECK_EQ(0, pthread_attr_init(&attr)); | ||
| 3626 | + // Don't shrink the thread's stack on FreeBSD. Said platform decided to | ||
| 3627 | + // follow the pthreads specification to the letter rather than in spirit: | ||
| 3628 | + // https://lists.freebsd.org/pipermail/freebsd-current/2014-March/048885.html | ||
| 3629 | + #ifndef __FreeBSD__ | ||
| 3630 | + CHECK_EQ(0, pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN)); | ||
| 3631 | + #endif // __FreeBSD__ | ||
| 3632 | + CHECK_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)); | ||
| 3633 | + sigset_t sigmask; | ||
| 3634 | + sigfillset(&sigmask); | ||
| 3635 | + CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &sigmask, &sigmask)); | ||
| 3636 | + pthread_t thread; | ||
| 3637 | + const int err = | ||
| 3638 | + pthread_create(&thread, &attr, DebugSignalThreadMain, nullptr); | ||
| 3639 | + CHECK_EQ(0, pthread_sigmask(SIG_SETMASK, &sigmask, nullptr)); | ||
| 3640 | + CHECK_EQ(0, pthread_attr_destroy(&attr)); | ||
| 3641 | + if (err != 0) { | ||
| 3642 | + fprintf(stderr, "node[%d]: pthread_create: %s\n", getpid(), strerror(err)); | ||
| 3643 | + fflush(stderr); | ||
| 3644 | + // Leave SIGUSR1 blocked. We don't install a signal handler, | ||
| 3645 | + // receiving the signal would terminate the process. | ||
| 3646 | + return -err; | ||
| 3647 | + } | ||
| 3619 | 3648 | RegisterSignalHandler(SIGUSR1, EnableDebugSignalHandler); | |
| 3620 | 3649 | // Unblock SIGUSR1. A pending SIGUSR1 signal will now be delivered. | |
| 3621 | - sigset_t sigmask; | ||
| 3622 | 3650 | sigemptyset(&sigmask); | |
| 3623 | 3651 | sigaddset(&sigmask, SIGUSR1); | |
| 3624 | 3652 | CHECK_EQ(0, pthread_sigmask(SIG_UNBLOCK, &sigmask, nullptr)); | |
@@ -3860,6 +3888,8 @@ void Init(int* argc, | |||
| 3860 | 3888 | // Make inherited handles noninheritable. | |
| 3861 | 3889 | uv_disable_stdio_inheritance(); | |
| 3862 | 3890 | ||
| 3891 | + CHECK_EQ(0, uv_mutex_init(&node_isolate_mutex)); | ||
| 3892 | + | ||
| 3863 | 3893 | // init async debug messages dispatching | |
| 3864 | 3894 | // Main thread uses uv_default_loop | |
| 3865 | 3895 | CHECK_EQ(0, uv_async_init(uv_default_loop(), | |
@@ -4146,15 +4176,18 @@ static void StartNodeInstance(void* arg) { | |||
| 4146 | 4176 | params.code_event_handler = vTune::GetVtuneCodeEventHandler(); | |
| 4147 | 4177 | #endif | |
| 4148 | 4178 | Isolate* isolate = Isolate::New(params); | |
| 4179 | + | ||
| 4180 | + uv_mutex_lock(&node_isolate_mutex); | ||
| 4181 | + if (instance_data->is_main()) { | ||
| 4182 | + CHECK_EQ(node_isolate, nullptr); | ||
| 4183 | + node_isolate = isolate; | ||
| 4184 | + } | ||
| 4185 | + uv_mutex_unlock(&node_isolate_mutex); | ||
| 4186 | + | ||
| 4149 | 4187 | if (track_heap_objects) { | |
| 4150 | 4188 | isolate->GetHeapProfiler()->StartTrackingHeapObjects(true); | |
| 4151 | 4189 | } | |
| 4152 | 4190 | ||
| 4153 | - // Fetch a reference to the main isolate, so we have a reference to it | ||
| 4154 | - // even when we need it to access it from another (debugger) thread. | ||
| 4155 | - if (instance_data->is_main()) | ||
| 4156 | - CHECK_EQ(nullptr, node_isolate.exchange(isolate)); | ||
| 4157 | - | ||
| 4158 | 4191 | { | |
| 4159 | 4192 | Locker locker(isolate); | |
| 4160 | 4193 | Isolate::Scope isolate_scope(isolate); | |
@@ -4218,10 +4251,10 @@ static void StartNodeInstance(void* arg) { | |||
| 4218 | 4251 | env = nullptr; | |
| 4219 | 4252 | } | |
| 4220 | 4253 | ||
| 4221 | - if (instance_data->is_main()) { | ||
| 4222 | - // Synchronize with signal handler, see TryStartDebugger. | ||
| 4223 | - while (isolate != node_isolate.exchange(nullptr)); // NOLINT | ||
| 4224 | - } | ||
| 4254 | + uv_mutex_lock(&node_isolate_mutex); | ||
| 4255 | + if (node_isolate == isolate) | ||
| 4256 | + node_isolate = nullptr; | ||
| 4257 | + uv_mutex_unlock(&node_isolate_mutex); | ||
| 4225 | 4258 | ||
| 4226 | 4259 | CHECK_NE(isolate, nullptr); | |
| 4227 | 4260 | isolate->Dispose(); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments