@@ -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
169169void Stop ();
170170
171171bool IsStarted ();
172- bool IsConnected (){return connected_ }
172+ bool IsConnected (){return state_ == State:: kConnected }
173173void WaitForDisconnect ();
174174
175175private:
176176using MessageQueue = std::vector<std::pair<int , String16>>
177+ enum class State {kNew , kAccepting , kConnected , kDone , kError };
177178
178179static void ThreadCbIO (void * agent);
179180static void OnSocketConnectionIO (uv_stream_t * server, int status);
@@ -194,6 +195,7 @@ class AgentImpl{
194195const String16& message);
195196void SwapBehindLock (MessageQueue* vector1, MessageQueue* vector2);
196197void PostIncomingMessage (const String16& message);
198+ State ToState (State state);
197199
198200uv_sem_t start_sem_;
199201 ConditionVariable pause_cond_;
@@ -204,8 +206,8 @@ class AgentImpl{
204206
205207int port_;
206208bool wait_;
207- bool connected_;
208209bool shutting_down_;
210+ State state_;
209211 node::Environment* parent_env_;
210212
211213uv_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(){
333335uv_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){
337339auto 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 );
347343CHECK_EQ (err, 0 );
348344
349345uv_unref (reinterpret_cast <uv_handle_t *>(&data_written_));
@@ -355,21 +351,20 @@ void AgentImpl::Start(v8::Platform* platform, int port, bool wait){
355351CHECK_EQ (err, 0 );
356352uv_sem_wait (&start_sem_);
357353
354+ if (state_ == State::kError ){
355+ Stop ();
356+ return false ;
357+ }
358+ state_ = State::kAccepting ;
358359if (wait){
359360DispatchMessages ();
360361 }
362+ return true ;
361363}
362364
363365void AgentImpl::Stop (){
364- // TODO(repenaxa): hop on the right thread.
365- DisconnectAndDisposeIO (client_socket_);
366366int err = uv_thread_join (&thread_);
367367CHECK_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 );
373368delete inspector_;
374369}
375370
@@ -428,7 +423,6 @@ void AgentImpl::OnRemoteDataIO(inspector_socket_t* socket,
428423 Mutex::ScopedLock scoped_lock (pause_lock_);
429424if (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 ;
438432uv_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
447437if (client_socket_ == socket){
@@ -476,8 +466,10 @@ void AgentImpl::WriteCbIO(uv_async_t* async){
476466void AgentImpl::WorkerRunIO (){
477467 sockaddr_in addr;
478468uv_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 ;
482474uv_tcp_init (&child_loop_, &server);
483475uv_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 ){
494484fprintf (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_);
497493if (!wait_){
498494uv_sem_post (&start_sem_);
499495 }
500496uv_run (&child_loop_, UV_RUN_DEFAULT);
501497uv_close (reinterpret_cast <uv_handle_t *>(&io_thread_req_), nullptr );
502498uv_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(){
543542for (const MessageQueue::value_type& pair : tasks){
544543const String16& message = pair.second ;
545544if (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 ;
549548fprintf (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 {
555555PrintDebuggerReadyMessage (port_);
556+ state_ = State::kAccepting ;
557+ }
556558 inspector_->quitMessageLoopOnPause ();
557559 inspector_->disconnectFrontend ();
558560 } else {
@@ -576,8 +578,8 @@ Agent::~Agent(){
576578delete 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