@@ -164,16 +164,17 @@ class AgentImpl {
164164 ~AgentImpl ();
165165
166166 // Start the inspector agent thread
167- void Start (v8::Platform* platform, int port, bool wait);
167+ bool Start (v8::Platform* platform, int port, bool wait);
168168 // Stop the inspector agent
169169 void Stop ();
170170
171171 bool IsStarted ();
172- bool IsConnected () { return connected_ ; }
172+ bool IsConnected () { return state_ == State:: kConnected ; }
173173 void WaitForDisconnect ();
174174
175175 private:
176176 using MessageQueue = std::vector<std::pair<int , String16>>;
177+ enum class State { kNew , kAccepting , kConnected , kDone , kError };
177178
178179 static void ThreadCbIO (void * agent);
179180 static void OnSocketConnectionIO (uv_stream_t * server, int status);
@@ -194,6 +195,7 @@ class AgentImpl {
194195 const String16& message);
195196 void SwapBehindLock (MessageQueue* vector1, MessageQueue* vector2);
196197 void PostIncomingMessage (const String16& message);
198+ State ToState (State state);
197199
198200 uv_sem_t start_sem_;
199201 ConditionVariable pause_cond_;
@@ -204,8 +206,8 @@ class AgentImpl {
204206
205207 int port_;
206208 bool wait_;
207- bool connected_;
208209 bool shutting_down_;
210+ State state_;
209211 node::Environment* parent_env_;
210212
211213 uv_async_t data_written_;
@@ -313,8 +315,8 @@ class V8NodeInspector : public blink::V8Inspector {
313315
314316AgentImpl::AgentImpl (Environment* env) : port_(0 ),
315317 wait_(false ),
316- connected_(false ),
317318 shutting_down_(false ),
319+ state_(State::kNew ),
318320 parent_env_(env),
319321 client_socket_(nullptr ),
320322 inspector_(nullptr ),
@@ -333,17 +335,11 @@ AgentImpl::~AgentImpl() {
333335 uv_close (reinterpret_cast <uv_handle_t *>(&data_written_), nullptr );
334336}
335337
336- void AgentImpl::Start (v8::Platform* platform, int port, bool wait) {
338+ bool AgentImpl::Start (v8::Platform* platform, int port, bool wait) {
337339 auto env = parent_env_;
338340 inspector_ = new V8NodeInspector (this , env, platform);
339-
340- int err;
341-
342341 platform_ = platform;
343-
344- err = uv_loop_init (&child_loop_);
345- CHECK_EQ (err, 0 );
346- err = uv_async_init (env->event_loop (), &data_written_, nullptr );
342+ int err = uv_async_init (env->event_loop (), &data_written_, nullptr );
347343 CHECK_EQ (err, 0 );
348344
349345 uv_unref (reinterpret_cast <uv_handle_t *>(&data_written_));
@@ -355,21 +351,20 @@ void AgentImpl::Start(v8::Platform* platform, int port, bool wait) {
355351 CHECK_EQ (err, 0 );
356352 uv_sem_wait (&start_sem_);
357353
354+ if (state_ == State::kError ) {
355+ Stop ();
356+ return false ;
357+ }
358+ state_ = State::kAccepting ;
358359 if (wait) {
359360 DispatchMessages ();
360361 }
362+ return true ;
361363}
362364
363365void AgentImpl::Stop () {
364- // TODO(repenaxa): hop on the right thread.
365- DisconnectAndDisposeIO (client_socket_);
366366 int err = uv_thread_join (&thread_);
367367 CHECK_EQ (err, 0 );
368-
369- uv_run (&child_loop_, UV_RUN_NOWAIT);
370-
371- err = uv_loop_close (&child_loop_);
372- CHECK_EQ (err, 0 );
373368 delete inspector_;
374369}
375370
@@ -428,7 +423,6 @@ void AgentImpl::OnRemoteDataIO(inspector_socket_t* socket,
428423 Mutex::ScopedLock scoped_lock (pause_lock_);
429424 if (read > 0 ) {
430425 String16 str = String16::fromUTF8 (buf->base , read);
431- PostIncomingMessage (str);
432426 // TODO(pfeldman): Instead of blocking execution while debugger
433427 // engages, node should wait for the run callback from the remote client
434428 // and initiate its startup. This is a change to node.cc that should be
@@ -437,11 +431,7 @@ void AgentImpl::OnRemoteDataIO(inspector_socket_t* socket,
437431 wait_ = false ;
438432 uv_sem_post (&start_sem_);
439433 }
440-
441- platform_->CallOnForegroundThread (parent_env_->isolate (),
442- new DispatchOnInspectorBackendTask (this ));
443- parent_env_->isolate ()->RequestInterrupt (InterruptCallback, this );
444- uv_async_send (&data_written_);
434+ PostIncomingMessage (str);
445435 } else if (read <= 0 ) {
446436 // EOF
447437 if (client_socket_ == socket) {
@@ -476,8 +466,10 @@ void AgentImpl::WriteCbIO(uv_async_t* async) {
476466void AgentImpl::WorkerRunIO () {
477467 sockaddr_in addr;
478468 uv_tcp_t server;
479- int err = uv_async_init (&child_loop_, &io_thread_req_, AgentImpl::WriteCbIO);
480- CHECK_EQ (0 , err);
469+ int err = uv_loop_init (&child_loop_);
470+ CHECK_EQ (err, 0 );
471+ err = uv_async_init (&child_loop_, &io_thread_req_, AgentImpl::WriteCbIO);
472+ CHECK_EQ (err, 0 );
481473 io_thread_req_.data = this ;
482474 uv_tcp_init (&child_loop_, &server);
483475 uv_ip4_addr (" 0.0.0.0" , port_, &addr);
@@ -488,19 +480,26 @@ void AgentImpl::WorkerRunIO() {
488480 err = uv_listen (reinterpret_cast <uv_stream_t *>(&server), 1 ,
489481 OnSocketConnectionIO);
490482 }
491- if (err == 0 ) {
492- PrintDebuggerReadyMessage (port_);
493- } else {
483+ if (err != 0 ) {
494484 fprintf (stderr, " Unable to open devtools socket: %s\n " , uv_strerror (err));
495- ABORT ();
485+ state_ = State::kError ; // Safe, main thread is waiting on semaphore
486+ uv_close (reinterpret_cast <uv_handle_t *>(&io_thread_req_), nullptr );
487+ uv_close (reinterpret_cast <uv_handle_t *>(&server), nullptr );
488+ uv_loop_close (&child_loop_);
489+ uv_sem_post (&start_sem_);
490+ return ;
496491 }
492+ PrintDebuggerReadyMessage (port_);
497493 if (!wait_) {
498494 uv_sem_post (&start_sem_);
499495 }
500496 uv_run (&child_loop_, UV_RUN_DEFAULT);
501497 uv_close (reinterpret_cast <uv_handle_t *>(&io_thread_req_), nullptr );
502498 uv_close (reinterpret_cast <uv_handle_t *>(&server), nullptr );
503- uv_run (&child_loop_, UV_RUN_DEFAULT);
499+ DisconnectAndDisposeIO (client_socket_);
500+ uv_run (&child_loop_, UV_RUN_NOWAIT);
501+ err = uv_loop_close (&child_loop_);
502+ CHECK_EQ (err, 0 );
504503}
505504
506505void AgentImpl::AppendMessage (MessageQueue* queue, int session_id,
@@ -543,16 +542,19 @@ void AgentImpl::DispatchMessages() {
543542 for (const MessageQueue::value_type& pair : tasks) {
544543 const String16& message = pair.second ;
545544 if (message == TAG_CONNECT) {
546- CHECK_EQ (false , connected_ );
545+ CHECK_EQ (State:: kAccepting , state_ );
547546 backend_session_id_++;
548- connected_ = true ;
547+ state_ = State:: kConnected ;
549548 fprintf (stderr, " Debugger attached.\n " );
550549 inspector_->connectFrontend (new ChannelImpl (this ));
551550 } else if (message == TAG_DISCONNECT) {
552- CHECK (connected_);
553- connected_ = false ;
554- if (!shutting_down_)
551+ CHECK_EQ (State::kConnected , state_);
552+ if (shutting_down_) {
553+ state_ = State::kDone ;
554+ } else {
555555 PrintDebuggerReadyMessage (port_);
556+ state_ = State::kAccepting ;
557+ }
556558 inspector_->quitMessageLoopOnPause ();
557559 inspector_->disconnectFrontend ();
558560 } else {
@@ -576,8 +578,8 @@ Agent::~Agent() {
576578 delete impl;
577579}
578580
579- void Agent::Start (v8::Platform* platform, int port, bool wait) {
580- impl->Start (platform, port, wait);
581+ bool Agent::Start (v8::Platform* platform, int port, bool wait) {
582+ return impl->Start (platform, port, wait);
581583}
582584
583585void Agent::Stop () {
0 commit comments