@@ -165,16 +165,17 @@ class AgentImpl {
165
165
~AgentImpl ();
166
166
167
167
// 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);
169
169
// Stop the inspector agent
170
170
void Stop ();
171
171
172
172
bool IsStarted ();
173
- bool IsConnected () { return connected_ ; }
173
+ bool IsConnected () { return state_ == State:: kConnected ; }
174
174
void WaitForDisconnect ();
175
175
176
176
private:
177
177
using MessageQueue = std::vector<std::pair<int , String16>>;
178
+ enum class State { kNew , kAccepting , kConnected , kDone , kError };
178
179
179
180
static void ThreadCbIO (void * agent);
180
181
static void OnSocketConnectionIO (uv_stream_t * server, int status);
@@ -195,6 +196,7 @@ class AgentImpl {
195
196
const String16& message);
196
197
void SwapBehindLock (MessageQueue* vector1, MessageQueue* vector2);
197
198
void PostIncomingMessage (const String16& message);
199
+ State ToState (State state);
198
200
199
201
uv_sem_t start_sem_;
200
202
ConditionVariable pause_cond_;
@@ -205,8 +207,8 @@ class AgentImpl {
205
207
206
208
int port_;
207
209
bool wait_;
208
- bool connected_;
209
210
bool shutting_down_;
211
+ State state_;
210
212
node::Environment* parent_env_;
211
213
212
214
uv_async_t data_written_;
@@ -314,8 +316,8 @@ class V8NodeInspector : public blink::V8Inspector {
314
316
315
317
AgentImpl::AgentImpl (Environment* env) : port_(0 ),
316
318
wait_(false ),
317
- connected_(false ),
318
319
shutting_down_(false ),
320
+ state_(State::kNew ),
319
321
parent_env_(env),
320
322
client_socket_(nullptr ),
321
323
inspector_(nullptr ),
@@ -334,17 +336,11 @@ AgentImpl::~AgentImpl() {
334
336
uv_close (reinterpret_cast <uv_handle_t *>(&data_written_), nullptr );
335
337
}
336
338
337
- void AgentImpl::Start (v8::Platform* platform, int port, bool wait) {
339
+ bool AgentImpl::Start (v8::Platform* platform, int port, bool wait) {
338
340
auto env = parent_env_;
339
341
inspector_ = new V8NodeInspector (this , env, platform);
340
-
341
- int err;
342
-
343
342
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 );
348
344
CHECK_EQ (err, 0 );
349
345
350
346
uv_unref (reinterpret_cast <uv_handle_t *>(&data_written_));
@@ -356,21 +352,20 @@ void AgentImpl::Start(v8::Platform* platform, int port, bool wait) {
356
352
CHECK_EQ (err, 0 );
357
353
uv_sem_wait (&start_sem_);
358
354
355
+ if (state_ == State::kError ) {
356
+ Stop ();
357
+ return false ;
358
+ }
359
+ state_ = State::kAccepting ;
359
360
if (wait ) {
360
361
DispatchMessages ();
361
362
}
363
+ return true ;
362
364
}
363
365
364
366
void AgentImpl::Stop () {
365
- // TODO(repenaxa): hop on the right thread.
366
- DisconnectAndDisposeIO (client_socket_);
367
367
int err = uv_thread_join (&thread_);
368
368
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 );
374
369
delete inspector_;
375
370
}
376
371
@@ -429,7 +424,6 @@ void AgentImpl::OnRemoteDataIO(inspector_socket_t* socket,
429
424
Mutex::ScopedLock scoped_lock (pause_lock_);
430
425
if (read > 0 ) {
431
426
String16 str = String16::fromUTF8 (buf->base , read );
432
- PostIncomingMessage (str);
433
427
// TODO(pfeldman): Instead of blocking execution while debugger
434
428
// engages, node should wait for the run callback from the remote client
435
429
// 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,
438
432
wait_ = false ;
439
433
uv_sem_post (&start_sem_);
440
434
}
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);
446
436
} else if (read <= 0 ) {
447
437
// EOF
448
438
if (client_socket_ == socket) {
@@ -477,8 +467,10 @@ void AgentImpl::WriteCbIO(uv_async_t* async) {
477
467
void AgentImpl::WorkerRunIO () {
478
468
sockaddr_in addr;
479
469
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 );
482
474
io_thread_req_.data = this ;
483
475
uv_tcp_init (&child_loop_, &server);
484
476
uv_ip4_addr (" 0.0.0.0" , port_, &addr);
@@ -489,19 +481,26 @@ void AgentImpl::WorkerRunIO() {
489
481
err = uv_listen (reinterpret_cast <uv_stream_t *>(&server), 1 ,
490
482
OnSocketConnectionIO);
491
483
}
492
- if (err == 0 ) {
493
- PrintDebuggerReadyMessage (port_);
494
- } else {
484
+ if (err != 0 ) {
495
485
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 ;
497
492
}
493
+ PrintDebuggerReadyMessage (port_);
498
494
if (!wait_) {
499
495
uv_sem_post (&start_sem_);
500
496
}
501
497
uv_run (&child_loop_, UV_RUN_DEFAULT);
502
498
uv_close (reinterpret_cast <uv_handle_t *>(&io_thread_req_), nullptr );
503
499
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 );
505
504
}
506
505
507
506
void AgentImpl::AppendMessage (MessageQueue* queue, int session_id,
@@ -544,16 +543,19 @@ void AgentImpl::DispatchMessages() {
544
543
for (const MessageQueue::value_type& pair : tasks) {
545
544
const String16& message = pair.second ;
546
545
if (message == TAG_CONNECT) {
547
- CHECK_EQ (false , connected_ );
546
+ CHECK_EQ (State:: kAccepting , state_ );
548
547
backend_session_id_++;
549
- connected_ = true ;
548
+ state_ = State:: kConnected ;
550
549
fprintf (stderr, " Debugger attached.\n " );
551
550
inspector_->connectFrontend (new ChannelImpl (this ));
552
551
} 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 {
556
556
PrintDebuggerReadyMessage (port_);
557
+ state_ = State::kAccepting ;
558
+ }
557
559
inspector_->quitMessageLoopOnPause ();
558
560
inspector_->disconnectFrontend ();
559
561
} else {
@@ -577,8 +579,8 @@ Agent::~Agent() {
577
579
delete impl;
578
580
}
579
581
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 );
582
584
}
583
585
584
586
void Agent::Stop () {
0 commit comments