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