@@ -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
315317AgentImpl::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
364366void 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) {
477467void 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
507506void 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
584586void Agent::Stop () {
0 commit comments