From 15b0ab1651e316538537a5dfb8be92827fc97daa Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Mon, 28 Jan 2019 23:53:39 +0100 Subject: [PATCH] src: add debug check for inspector uv_async_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a check to make sure start_io_thread_async is not accidentally re-used or used when uninitialized. (This is a bit of an odd check imo, but it helped me figure out a real issue and it might do so again, so… why not?) PR-URL: https://github.com/nodejs/node/pull/25777 Reviewed-By: Eugene Ostroukhov Reviewed-By: Minwoo Jung Reviewed-By: James M Snell --- src/inspector_agent.cc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc index 2d919b9210bf65..fb85a54408e19c 100644 --- a/src/inspector_agent.cc +++ b/src/inspector_agent.cc @@ -51,6 +51,9 @@ using v8_inspector::V8InspectorClient; static uv_sem_t start_io_thread_semaphore; static uv_async_t start_io_thread_async; +// This is just an additional check to make sure start_io_thread_async +// is not accidentally re-used or used when uninitialized. +static std::atomic_bool start_io_thread_async_initialized { false }; class StartIoTask : public Task { public: @@ -88,6 +91,7 @@ static void StartIoThreadWakeup(int signo) { inline void* StartIoThreadMain(void* unused) { for (;;) { uv_sem_wait(&start_io_thread_semaphore); + CHECK(start_io_thread_async_initialized); Agent* agent = static_cast(start_io_thread_async.data); if (agent != nullptr) agent->RequestIoThreadStart(); @@ -141,6 +145,7 @@ static int StartDebugSignalHandler() { #ifdef _WIN32 DWORD WINAPI StartIoThreadProc(void* arg) { + CHECK(start_io_thread_async_initialized); Agent* agent = static_cast(start_io_thread_async.data); if (agent != nullptr) agent->RequestIoThreadStart(); @@ -664,6 +669,7 @@ Agent::Agent(Environment* env) Agent::~Agent() { if (start_io_thread_async.data == this) { + CHECK(start_io_thread_async_initialized.exchange(false)); start_io_thread_async.data = nullptr; // This is global, will never get freed uv_close(reinterpret_cast(&start_io_thread_async), nullptr); @@ -681,6 +687,7 @@ bool Agent::Start(const std::string& path, client_ = std::make_shared(parent_env_, is_main); if (parent_env_->is_main_thread()) { + CHECK_EQ(start_io_thread_async_initialized.exchange(true), false); CHECK_EQ(0, uv_async_init(parent_env_->event_loop(), &start_io_thread_async, StartIoThreadAsyncCallback)); @@ -847,6 +854,7 @@ void Agent::RequestIoThreadStart() { // We need to attempt to interrupt V8 flow (in case Node is running // continuous JS code) and to wake up libuv thread (in case Node is waiting // for IO events) + CHECK(start_io_thread_async_initialized); uv_async_send(&start_io_thread_async); Isolate* isolate = parent_env_->isolate(); v8::Platform* platform = parent_env_->isolate_data()->platform(); @@ -854,6 +862,7 @@ void Agent::RequestIoThreadStart() { platform->GetForegroundTaskRunner(isolate); taskrunner->PostTask(std::make_unique(this)); isolate->RequestInterrupt(StartIoInterrupt, this); + CHECK(start_io_thread_async_initialized); uv_async_send(&start_io_thread_async); }