inspector: Do not crash if the port is n/a · nodejs/node@f789eb3
@@ -165,16 +165,17 @@ class AgentImpl {
165165~AgentImpl();
166166167167// 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
170170void Stop();
171171172172bool IsStarted();
173-bool IsConnected() { return connected_; }
173+bool IsConnected() { return state_ == State::kConnected; }
174174void WaitForDisconnect();
175175176176private:
177177using MessageQueue = std::vector<std::pair<int, String16>>;
178+enum class State { kNew, kAccepting, kConnected, kDone, kError };
178179179180static void ThreadCbIO(void* agent);
180181static void OnSocketConnectionIO(uv_stream_t* server, int status);
@@ -195,6 +196,7 @@ class AgentImpl {
195196const String16& message);
196197void SwapBehindLock(MessageQueue* vector1, MessageQueue* vector2);
197198void PostIncomingMessage(const String16& message);
199+ State ToState(State state);
198200199201uv_sem_t start_sem_;
200202 ConditionVariable pause_cond_;
@@ -205,8 +207,8 @@ class AgentImpl {
205207206208int port_;
207209bool wait_;
208-bool connected_;
209210bool shutting_down_;
211+ State state_;
210212 node::Environment* parent_env_;
211213212214uv_async_t data_written_;
@@ -314,8 +316,8 @@ class V8NodeInspector : public blink::V8Inspector {
314316315317AgentImpl::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() {
334336uv_close(reinterpret_cast<uv_handle_t*>(&data_written_), nullptr);
335337}
336338337-void AgentImpl::Start(v8::Platform* platform, int port, bool wait) {
339+bool AgentImpl::Start(v8::Platform* platform, int port, bool wait) {
338340auto 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);
348344CHECK_EQ(err, 0);
349345350346uv_unref(reinterpret_cast<uv_handle_t*>(&data_written_));
@@ -356,21 +352,20 @@ void AgentImpl::Start(v8::Platform* platform, int port, bool wait) {
356352CHECK_EQ(err, 0);
357353uv_sem_wait(&start_sem_);
358354355+if (state_ == State::kError) {
356+Stop();
357+return false;
358+ }
359+ state_ = State::kAccepting;
359360if (wait) {
360361DispatchMessages();
361362 }
363+return true;
362364}
363365364366void AgentImpl::Stop() {
365-// TODO(repenaxa): hop on the right thread.
366-DisconnectAndDisposeIO(client_socket_);
367367int err = uv_thread_join(&thread_);
368368CHECK_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);
374369delete inspector_;
375370}
376371@@ -429,7 +424,6 @@ void AgentImpl::OnRemoteDataIO(inspector_socket_t* socket,
429424 Mutex::ScopedLock scoped_lock(pause_lock_);
430425if (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;
439433uv_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
448438if (client_socket_ == socket) {
@@ -477,8 +467,10 @@ void AgentImpl::WriteCbIO(uv_async_t* async) {
477467void AgentImpl::WorkerRunIO() {
478468 sockaddr_in addr;
479469uv_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;
483475uv_tcp_init(&child_loop_, &server);
484476uv_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) {
495485fprintf(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_);
498494if (!wait_) {
499495uv_sem_post(&start_sem_);
500496 }
501497uv_run(&child_loop_, UV_RUN_DEFAULT);
502498uv_close(reinterpret_cast<uv_handle_t*>(&io_thread_req_), nullptr);
503499uv_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}
506505507506void AgentImpl::AppendMessage(MessageQueue* queue, int session_id,
@@ -544,16 +543,19 @@ void AgentImpl::DispatchMessages() {
544543for (const MessageQueue::value_type& pair : tasks) {
545544const String16& message = pair.second;
546545if (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;
550549fprintf(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 {
556556PrintDebuggerReadyMessage(port_);
557+ state_ = State::kAccepting;
558+ }
557559 inspector_->quitMessageLoopOnPause();
558560 inspector_->disconnectFrontend();
559561 } else {
@@ -577,8 +579,8 @@ Agent::~Agent() {
577579delete impl;
578580}
579581580-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}
583585584586void Agent::Stop() {