Skip to content

Commit f789eb3

Browse files
Eugene Ostroukhovofrobots
Eugene Ostroukhov
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

File tree

4 files changed

+55
-47
lines changed

4 files changed

+55
-47
lines changed

doc/api/process.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,8 +1643,9 @@ cases:
16431643
source code internal in Node.js's bootstrapping process threw an error
16441644
when the bootstrapping function was called. This is extremely rare,
16451645
and generally can only happen during development of Node.js itself.
1646-
* `12` **Invalid Debug Argument** - The `--debug` and/or `--debug-brk`
1647-
options were set, but an invalid port number was chosen.
1646+
* `12` **Invalid Debug Argument** - The `--debug`, `--inspect` and/or
1647+
`--debug-brk` options were set, but the port number chosen was invalid
1648+
or unavailable.
16481649
* `>128` **Signal Exits** - If Node.js receives a fatal signal such as
16491650
`SIGKILL` or `SIGHUP`, then its exit code will be `128` plus the
16501651
value of the signal code. This is a standard Unix practice, since

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
Original file line numberDiff line numberDiff line change
@@ -208,9 +208,11 @@ static struct {
208208
platform_ = nullptr;
209209
}
210210

211-
void StartInspector(Environment *env, int port, bool wait) {
211+
bool StartInspector(Environment *env, int port, bool wait) {
212212
#if HAVE_INSPECTOR
213-
env->inspector_agent()->Start(platform_, port, wait);
213+
return env->inspector_agent()->Start(platform_, port, wait);
214+
#else
215+
return true;
214216
#endif // HAVE_INSPECTOR
215217
}
216218

@@ -3756,8 +3758,7 @@ static void DispatchMessagesDebugAgentCallback(Environment* env) {
37563758
static void StartDebug(Environment* env, bool wait) {
37573759
CHECK(!debugger_running);
37583760
if (use_inspector) {
3759-
v8_platform.StartInspector(env, inspector_port, wait);
3760-
debugger_running = true;
3761+
debugger_running = v8_platform.StartInspector(env, inspector_port, wait);
37613762
} else {
37623763
env->debugger_agent()->set_dispatch_handler(
37633764
DispatchMessagesDebugAgentCallback);
@@ -4383,8 +4384,12 @@ static void StartNodeInstance(void* arg) {
43834384
ShouldAbortOnUncaughtException);
43844385

43854386
// Start debug agent when argv has --debug
4386-
if (instance_data->use_debug_agent())
4387+
if (instance_data->use_debug_agent()) {
43874388
StartDebug(&env, debug_wait_connect);
4389+
if (use_inspector && !debugger_running) {
4390+
exit(12);
4391+
}
4392+
}
43884393

43894394
{
43904395
Environment::AsyncCallbackScope callback_scope(&env);

0 commit comments

Comments
 (0)