20
20
namespace node {
21
21
namespace inspector {
22
22
namespace {
23
+ using AsyncAndAgent = std::pair<uv_async_t , Agent*>;
23
24
using v8_inspector::StringBuffer;
24
25
using v8_inspector::StringView;
25
26
@@ -96,6 +97,12 @@ int CloseAsyncAndLoop(uv_async_t* async) {
96
97
return uv_loop_close (async->loop );
97
98
}
98
99
100
+ void ReleasePairOnAsyncClose (uv_handle_t * async) {
101
+ AsyncAndAgent* pair = node::ContainerOf (&AsyncAndAgent::first,
102
+ reinterpret_cast <uv_async_t *>(async));
103
+ delete pair;
104
+ }
105
+
99
106
} // namespace
100
107
101
108
std::unique_ptr<StringBuffer> Utf8ToStringView (const std::string& message) {
@@ -127,6 +134,9 @@ class InspectorIoDelegate: public node::inspector::SocketServerDelegate {
127
134
std::string GetTargetTitle (const std::string& id) override ;
128
135
std::string GetTargetUrl (const std::string& id) override ;
129
136
bool IsConnected () { return connected_; }
137
+ void ServerDone () override {
138
+ io_->ServerDone ();
139
+ }
130
140
private:
131
141
InspectorIo* io_;
132
142
bool connected_;
@@ -137,53 +147,70 @@ class InspectorIoDelegate: public node::inspector::SocketServerDelegate {
137
147
bool waiting_;
138
148
};
139
149
140
- void InterruptCallback (v8::Isolate*, void * io) {
141
- static_cast <InspectorIo*>(io)->DispatchMessages ();
150
+ void InterruptCallback (v8::Isolate*, void * agent) {
151
+ InspectorIo* io = static_cast <Agent*>(agent)->io ();
152
+ if (io != nullptr )
153
+ io->DispatchMessages ();
142
154
}
143
155
144
- class DispatchOnInspectorBackendTask : public v8 ::Task {
156
+ class DispatchMessagesTask : public v8 ::Task {
145
157
public:
146
- explicit DispatchOnInspectorBackendTask (InspectorIo* io ) : io_(io ) {}
158
+ explicit DispatchMessagesTask (Agent* agent ) : agent_(agent ) {}
147
159
148
160
void Run () override {
149
- io_->DispatchMessages ();
161
+ InspectorIo* io = agent_->io ();
162
+ if (io != nullptr )
163
+ io->DispatchMessages ();
150
164
}
151
165
152
166
private:
153
- InspectorIo* io_ ;
167
+ Agent* agent_ ;
154
168
};
155
169
156
170
InspectorIo::InspectorIo (Environment* env, v8::Platform* platform,
157
- const std::string& path, const DebugOptions& options)
171
+ const std::string& path, const DebugOptions& options,
172
+ bool wait_for_connect)
158
173
: options_(options), thread_(), delegate_(nullptr ),
159
- shutting_down_ (false ), state_(State::kNew ),
160
- parent_env_(env), io_thread_req_(),
161
- platform_(platform), dispatching_messages_(false ),
162
- session_id_(0 ), script_name_(path) {
163
- CHECK_EQ (0 , uv_async_init (env->event_loop (), &main_thread_req_,
174
+ state_ (State::kNew ), parent_env_(env),
175
+ io_thread_req_(), platform_(platform),
176
+ dispatching_messages_(false ), session_id_(0 ),
177
+ script_name_(path),
178
+ wait_for_connect_(wait_for_connect) {
179
+ main_thread_req_ = new AsyncAndAgent ({uv_async_t (), env->inspector_agent ()});
180
+ CHECK_EQ (0 , uv_async_init (env->event_loop (), &main_thread_req_->first ,
164
181
InspectorIo::MainThreadAsyncCb));
165
- uv_unref (reinterpret_cast <uv_handle_t *>(&main_thread_req_));
182
+ uv_unref (reinterpret_cast <uv_handle_t *>(&main_thread_req_-> first ));
166
183
CHECK_EQ (0 , uv_sem_init (&start_sem_, 0 ));
167
184
}
168
185
186
+ InspectorIo::~InspectorIo () {
187
+ uv_sem_destroy (&start_sem_);
188
+ uv_close (reinterpret_cast <uv_handle_t *>(&main_thread_req_->first ),
189
+ ReleasePairOnAsyncClose);
190
+ }
191
+
169
192
bool InspectorIo::Start () {
193
+ CHECK_EQ (state_, State::kNew );
170
194
CHECK_EQ (uv_thread_create (&thread_, InspectorIo::ThreadCbIO, this ), 0 );
171
195
uv_sem_wait (&start_sem_);
172
196
173
197
if (state_ == State::kError ) {
174
- Stop ();
175
198
return false ;
176
199
}
177
200
state_ = State::kAccepting ;
178
- if (options_. wait_for_connect () ) {
201
+ if (wait_for_connect_ ) {
179
202
DispatchMessages ();
180
203
}
181
204
return true ;
182
205
}
183
206
184
207
void InspectorIo::Stop () {
208
+ CHECK (state_ == State::kAccepting || state_ == State::kConnected );
209
+ Write (TransportAction::kKill , 0 , StringView ());
185
210
int err = uv_thread_join (&thread_);
186
211
CHECK_EQ (err, 0 );
212
+ state_ = State::kShutDown ;
213
+ DispatchMessages ();
187
214
}
188
215
189
216
bool InspectorIo::IsConnected () {
@@ -195,8 +222,10 @@ bool InspectorIo::IsStarted() {
195
222
}
196
223
197
224
void InspectorIo::WaitForDisconnect () {
225
+ if (state_ == State::kAccepting )
226
+ state_ = State::kDone ;
198
227
if (state_ == State::kConnected ) {
199
- shutting_down_ = true ;
228
+ state_ = State:: kShutDown ;
200
229
Write (TransportAction::kStop , 0 , StringView ());
201
230
fprintf (stderr, " Waiting for the debugger to disconnect...\n " );
202
231
fflush (stderr);
@@ -222,6 +251,9 @@ void InspectorIo::WriteCbIO(uv_async_t* async) {
222
251
io->SwapBehindLock (&io->outgoing_message_queue_ , &outgoing_messages);
223
252
for (const auto & outgoing : outgoing_messages) {
224
253
switch (std::get<0 >(outgoing)) {
254
+ case TransportAction::kKill :
255
+ io_and_transport->first ->TerminateConnections ();
256
+ // Fallthrough
225
257
case TransportAction::kStop :
226
258
io_and_transport->first ->Stop (nullptr );
227
259
break ;
@@ -253,7 +285,7 @@ void InspectorIo::WorkerRunIO() {
253
285
uv_fs_req_cleanup (&req);
254
286
}
255
287
InspectorIoDelegate delegate (this , script_path, script_name_,
256
- options_. wait_for_connect () );
288
+ wait_for_connect_ );
257
289
delegate_ = &delegate;
258
290
InspectorSocketServer server (&delegate,
259
291
options_.host_name (),
@@ -266,14 +298,12 @@ void InspectorIo::WorkerRunIO() {
266
298
uv_sem_post (&start_sem_);
267
299
return ;
268
300
}
269
- if (!options_. wait_for_connect () ) {
301
+ if (!wait_for_connect_ ) {
270
302
uv_sem_post (&start_sem_);
271
303
}
272
304
uv_run (&loop, UV_RUN_DEFAULT);
273
305
io_thread_req_.data = nullptr ;
274
- server.Stop (nullptr );
275
- server.TerminateConnections (nullptr );
276
- CHECK_EQ (CloseAsyncAndLoop (&io_thread_req_), 0 );
306
+ CHECK_EQ (uv_loop_close (&loop), 0 );
277
307
delegate_ = nullptr ;
278
308
}
279
309
@@ -298,11 +328,12 @@ void InspectorIo::PostIncomingMessage(InspectorAction action, int session_id,
298
328
const std::string& message) {
299
329
if (AppendMessage (&incoming_message_queue_, action, session_id,
300
330
Utf8ToStringView (message))) {
331
+ Agent* agent = main_thread_req_->second ;
301
332
v8::Isolate* isolate = parent_env_->isolate ();
302
333
platform_->CallOnForegroundThread (isolate,
303
- new DispatchOnInspectorBackendTask ( this ));
304
- isolate->RequestInterrupt (InterruptCallback, this );
305
- CHECK_EQ (0 , uv_async_send (&main_thread_req_));
334
+ new DispatchMessagesTask (agent ));
335
+ isolate->RequestInterrupt (InterruptCallback, agent );
336
+ CHECK_EQ (0 , uv_async_send (&main_thread_req_-> first ));
306
337
}
307
338
NotifyMessageReceived ();
308
339
}
@@ -344,7 +375,7 @@ void InspectorIo::DispatchMessages() {
344
375
break ;
345
376
case InspectorAction::kEndSession :
346
377
CHECK_NE (session_delegate_, nullptr );
347
- if (shutting_down_ ) {
378
+ if (state_ == State:: kShutDown ) {
348
379
state_ = State::kDone ;
349
380
} else {
350
381
state_ = State::kAccepting ;
@@ -363,12 +394,18 @@ void InspectorIo::DispatchMessages() {
363
394
364
395
// static
365
396
void InspectorIo::MainThreadAsyncCb (uv_async_t * req) {
366
- InspectorIo* io = node::ContainerOf (&InspectorIo::main_thread_req_, req);
367
- io->DispatchMessages ();
397
+ AsyncAndAgent* pair = node::ContainerOf (&AsyncAndAgent::first, req);
398
+ // Note that this may be called after io was closed or even after a new
399
+ // one was created and ran.
400
+ InspectorIo* io = pair->second ->io ();
401
+ if (io != nullptr )
402
+ io->DispatchMessages ();
368
403
}
369
404
370
405
void InspectorIo::Write (TransportAction action, int session_id,
371
406
const StringView& inspector_message) {
407
+ if (state_ == State::kShutDown )
408
+ return ;
372
409
AppendMessage (&outgoing_message_queue_, action, session_id,
373
410
StringBuffer::create (inspector_message));
374
411
int err = uv_async_send (&io_thread_req_);
0 commit comments