inspector: Do not crash if the port is n/a · nodejs/node@f789eb3 · GitHub
Skip to content

Commit f789eb3

Browse files
Eugene Ostroukhovofrobots
authored andcommitted
inspector: Do not crash if the port is n/a
Node process will no longer terminate with an assertion if the inspector port is not available. PR-URL: #7874 Reviewed-By: bnoordhuis - Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: jasnell - James M Snell <jasnell@gmail.com>
1 parent 7d75338 commit f789eb3

4 files changed

Lines changed: 55 additions & 47 deletions

File tree

doc/api/process.md

Lines changed: 3 additions & 2 deletions

src/inspector_agent.cc

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -165,16 +165,17 @@ class AgentImpl {
165165
~AgentImpl();
166166

167167
// Start the inspector agent thread
168-
void Start(v8::Platform* platform, int port, bool wait);
168+
bool Start(v8::Platform* platform, int port, bool wait);
169169
// Stop the inspector agent
170170
void Stop();
171171

172172
bool IsStarted();
173-
bool IsConnected() { return connected_; }
173+
bool IsConnected() { return state_ == State::kConnected; }
174174
void WaitForDisconnect();
175175

176176
private:
177177
using MessageQueue = std::vector<std::pair<int, String16>>;
178+
enum class State { kNew, kAccepting, kConnected, kDone, kError };
178179

179180
static void ThreadCbIO(void* agent);
180181
static void OnSocketConnectionIO(uv_stream_t* server, int status);
@@ -195,6 +196,7 @@ class AgentImpl {
195196
const String16& message);
196197
void SwapBehindLock(MessageQueue* vector1, MessageQueue* vector2);
197198
void PostIncomingMessage(const String16& message);
199+
State ToState(State state);
198200

199201
uv_sem_t start_sem_;
200202
ConditionVariable pause_cond_;
@@ -205,8 +207,8 @@ class AgentImpl {
205207

206208
int port_;
207209
bool wait_;
208-
bool connected_;
209210
bool shutting_down_;
211+
State state_;
210212
node::Environment* parent_env_;
211213

212214
uv_async_t data_written_;
@@ -314,8 +316,8 @@ class V8NodeInspector : public blink::V8Inspector {
314316

315317
AgentImpl::AgentImpl(Environment* env) : port_(0),
316318
wait_(false),
317-
connected_(false),
318319
shutting_down_(false),
320+
state_(State::kNew),
319321
parent_env_(env),
320322
client_socket_(nullptr),
321323
inspector_(nullptr),
@@ -334,17 +336,11 @@ AgentImpl::~AgentImpl() {
334336
uv_close(reinterpret_cast<uv_handle_t*>(&data_written_), nullptr);
335337
}
336338

337-
void AgentImpl::Start(v8::Platform* platform, int port, bool wait) {
339+
bool AgentImpl::Start(v8::Platform* platform, int port, bool wait) {
338340
auto env = parent_env_;
339341
inspector_ = new V8NodeInspector(this, env, platform);
340-
341-
int err;
342-
343342
platform_ = platform;
344-
345-
err = uv_loop_init(&child_loop_);
346-
CHECK_EQ(err, 0);
347-
err = uv_async_init(env->event_loop(), &data_written_, nullptr);
343+
int err = uv_async_init(env->event_loop(), &data_written_, nullptr);
348344
CHECK_EQ(err, 0);
349345

350346
uv_unref(reinterpret_cast<uv_handle_t*>(&data_written_));
@@ -356,21 +352,20 @@ void AgentImpl::Start(v8::Platform* platform, int port, bool wait) {
356352
CHECK_EQ(err, 0);
357353
uv_sem_wait(&start_sem_);
358354

355+
if (state_ == State::kError) {
356+
Stop();
357+
return false;
358+
}
359+
state_ = State::kAccepting;
359360
if (wait) {
360361
DispatchMessages();
361362
}
363+
return true;
362364
}
363365

364366
void AgentImpl::Stop() {
365-
// TODO(repenaxa): hop on the right thread.
366-
DisconnectAndDisposeIO(client_socket_);
367367
int err = uv_thread_join(&thread_);
368368
CHECK_EQ(err, 0);
369-
370-
uv_run(&child_loop_, UV_RUN_NOWAIT);
371-
372-
err = uv_loop_close(&child_loop_);
373-
CHECK_EQ(err, 0);
374369
delete inspector_;
375370
}
376371

@@ -429,7 +424,6 @@ void AgentImpl::OnRemoteDataIO(inspector_socket_t* socket,
429424
Mutex::ScopedLock scoped_lock(pause_lock_);
430425
if (read > 0) {
431426
String16 str = String16::fromUTF8(buf->base, read);
432-
PostIncomingMessage(str);
433427
// TODO(pfeldman): Instead of blocking execution while debugger
434428
// engages, node should wait for the run callback from the remote client
435429
// and initiate its startup. This is a change to node.cc that should be
@@ -438,11 +432,7 @@ void AgentImpl::OnRemoteDataIO(inspector_socket_t* socket,
438432
wait_ = false;
439433
uv_sem_post(&start_sem_);
440434
}
441-
442-
platform_->CallOnForegroundThread(parent_env_->isolate(),
443-
new DispatchOnInspectorBackendTask(this));
444-
parent_env_->isolate()->RequestInterrupt(InterruptCallback, this);
445-
uv_async_send(&data_written_);
435+
PostIncomingMessage(str);
446436
} else if (read <= 0) {
447437
// EOF
448438
if (client_socket_ == socket) {
@@ -477,8 +467,10 @@ void AgentImpl::WriteCbIO(uv_async_t* async) {
477467
void AgentImpl::WorkerRunIO() {
478468
sockaddr_in addr;
479469
uv_tcp_t server;
480-
int err = uv_async_init(&child_loop_, &io_thread_req_, AgentImpl::WriteCbIO);
481-
CHECK_EQ(0, err);
470+
int err = uv_loop_init(&child_loop_);
471+
CHECK_EQ(err, 0);
472+
err = uv_async_init(&child_loop_, &io_thread_req_, AgentImpl::WriteCbIO);
473+
CHECK_EQ(err, 0);
482474
io_thread_req_.data = this;
483475
uv_tcp_init(&child_loop_, &server);
484476
uv_ip4_addr("0.0.0.0", port_, &addr);
@@ -489,19 +481,26 @@ void AgentImpl::WorkerRunIO() {
489481
err = uv_listen(reinterpret_cast<uv_stream_t*>(&server), 1,
490482
OnSocketConnectionIO);
491483
}
492-
if (err == 0) {
493-
PrintDebuggerReadyMessage(port_);
494-
} else {
484+
if (err != 0) {
495485
fprintf(stderr, "Unable to open devtools socket: %s\n", uv_strerror(err));
496-
ABORT();
486+
state_ = State::kError; // Safe, main thread is waiting on semaphore
487+
uv_close(reinterpret_cast<uv_handle_t*>(&io_thread_req_), nullptr);
488+
uv_close(reinterpret_cast<uv_handle_t*>(&server), nullptr);
489+
uv_loop_close(&child_loop_);
490+
uv_sem_post(&start_sem_);
491+
return;
497492
}
493+
PrintDebuggerReadyMessage(port_);
498494
if (!wait_) {
499495
uv_sem_post(&start_sem_);
500496
}
501497
uv_run(&child_loop_, UV_RUN_DEFAULT);
502498
uv_close(reinterpret_cast<uv_handle_t*>(&io_thread_req_), nullptr);
503499
uv_close(reinterpret_cast<uv_handle_t*>(&server), nullptr);
504-
uv_run(&child_loop_, UV_RUN_DEFAULT);
500+
DisconnectAndDisposeIO(client_socket_);
501+
uv_run(&child_loop_, UV_RUN_NOWAIT);
502+
err = uv_loop_close(&child_loop_);
503+
CHECK_EQ(err, 0);
505504
}
506505

507506
void AgentImpl::AppendMessage(MessageQueue* queue, int session_id,
@@ -544,16 +543,19 @@ void AgentImpl::DispatchMessages() {
544543
for (const MessageQueue::value_type& pair : tasks) {
545544
const String16& message = pair.second;
546545
if (message == TAG_CONNECT) {
547-
CHECK_EQ(false, connected_);
546+
CHECK_EQ(State::kAccepting, state_);
548547
backend_session_id_++;
549-
connected_ = true;
548+
state_ = State::kConnected;
550549
fprintf(stderr, "Debugger attached.\n");
551550
inspector_->connectFrontend(new ChannelImpl(this));
552551
} else if (message == TAG_DISCONNECT) {
553-
CHECK(connected_);
554-
connected_ = false;
555-
if (!shutting_down_)
552+
CHECK_EQ(State::kConnected, state_);
553+
if (shutting_down_) {
554+
state_ = State::kDone;
555+
} else {
556556
PrintDebuggerReadyMessage(port_);
557+
state_ = State::kAccepting;
558+
}
557559
inspector_->quitMessageLoopOnPause();
558560
inspector_->disconnectFrontend();
559561
} else {
@@ -577,8 +579,8 @@ Agent::~Agent() {
577579
delete impl;
578580
}
579581

580-
void Agent::Start(v8::Platform* platform, int port, bool wait) {
581-
impl->Start(platform, port, wait);
582+
bool Agent::Start(v8::Platform* platform, int port, bool wait) {
583+
return impl->Start(platform, port, wait);
582584
}
583585

584586
void Agent::Stop() {

src/inspector_agent.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class Agent {
2525
~Agent();
2626

2727
// Start the inspector agent thread
28-
void Start(v8::Platform* platform, int port, bool wait);
28+
bool Start(v8::Platform* platform, int port, bool wait);
2929
// Stop the inspector agent
3030
void Stop();
3131

src/node.cc

Lines changed: 10 additions & 5 deletions

0 commit comments

Comments
 (0)