Skip to content

Commit

Permalink
src: add debug check for inspector uv_async_t
Browse files Browse the repository at this point in the history
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: #25777
Reviewed-By: Eugene Ostroukhov <eostroukhov@google.com>
Reviewed-By: Minwoo Jung <minwoo@nodesource.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
addaleax committed Jan 30, 2019
1 parent 0949039 commit 3f080d1
Showing 1 changed file with 9 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/inspector_agent.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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<Agent*>(start_io_thread_async.data);
if (agent != nullptr)
agent->RequestIoThreadStart();
Expand Down Expand Up @@ -141,6 +145,7 @@ static int StartDebugSignalHandler() {

#ifdef _WIN32
DWORD WINAPI StartIoThreadProc(void* arg) {
CHECK(start_io_thread_async_initialized);
Agent* agent = static_cast<Agent*>(start_io_thread_async.data);
if (agent != nullptr)
agent->RequestIoThreadStart();
Expand Down Expand Up @@ -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<uv_handle_t*>(&start_io_thread_async), nullptr);
Expand All @@ -681,6 +687,7 @@ bool Agent::Start(const std::string& path,

client_ = std::make_shared<NodeInspectorClient>(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));
Expand Down Expand Up @@ -847,13 +854,15 @@ 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();
std::shared_ptr<TaskRunner> taskrunner =
platform->GetForegroundTaskRunner(isolate);
taskrunner->PostTask(std::make_unique<StartIoTask>(this));
isolate->RequestInterrupt(StartIoInterrupt, this);
CHECK(start_io_thread_async_initialized);
uv_async_send(&start_io_thread_async);
}

Expand Down

0 comments on commit 3f080d1

Please sign in to comment.