@@ -285,22 +285,33 @@ void PerIsolatePlatformData::Shutdown() {
285
285
// effectively deleting the tasks instead of running them.
286
286
foreground_delayed_tasks_.PopAll ();
287
287
foreground_tasks_.PopAll ();
288
+ scheduled_delayed_tasks_.clear ();
288
289
289
- CancelPendingDelayedTasks ();
290
-
291
- ShutdownCbList* copy = new ShutdownCbList (std::move (shutdown_callbacks_));
292
- flush_tasks_->data = copy;
290
+ // Both destroying the scheduled_delayed_tasks_ lists and closing
291
+ // flush_tasks_ handle add tasks to the event loop. We keep a count of all
292
+ // non-closed handles, and when that reaches zero, we inform any shutdown
293
+ // callbacks that the platform is done as far as this Isolate is concerned.
294
+ self_reference_ = shared_from_this ();
293
295
uv_close (reinterpret_cast <uv_handle_t *>(flush_tasks_),
294
296
[](uv_handle_t * handle) {
295
- std::unique_ptr<ShutdownCbList> callbacks (
296
- static_cast <ShutdownCbList*>(handle->data ));
297
- for (const auto & callback : *callbacks)
298
- callback.cb (callback.data );
299
- delete reinterpret_cast <uv_async_t *>(handle);
297
+ std::unique_ptr<uv_async_t > flush_tasks {
298
+ reinterpret_cast <uv_async_t *>(handle) };
299
+ PerIsolatePlatformData* platform_data =
300
+ static_cast <PerIsolatePlatformData*>(flush_tasks->data );
301
+ platform_data->DecreaseHandleCount ();
302
+ platform_data->self_reference_ .reset ();
300
303
});
301
304
flush_tasks_ = nullptr ;
302
305
}
303
306
307
+ void PerIsolatePlatformData::DecreaseHandleCount () {
308
+ CHECK_GE (uv_handle_count_, 1 );
309
+ if (--uv_handle_count_ == 0 ) {
310
+ for (const auto & callback : shutdown_callbacks_)
311
+ callback.cb (callback.data );
312
+ }
313
+ }
314
+
304
315
NodePlatform::NodePlatform (int thread_pool_size,
305
316
TracingController* tracing_controller) {
306
317
if (tracing_controller) {
@@ -382,10 +393,6 @@ void PerIsolatePlatformData::RunForegroundTask(uv_timer_t* handle) {
382
393
delayed->platform_data ->DeleteFromScheduledTasks (delayed);
383
394
}
384
395
385
- void PerIsolatePlatformData::CancelPendingDelayedTasks () {
386
- scheduled_delayed_tasks_.clear ();
387
- }
388
-
389
396
void NodePlatform::DrainTasks (Isolate* isolate) {
390
397
std::shared_ptr<PerIsolatePlatformData> per_isolate = ForIsolate (isolate);
391
398
@@ -409,12 +416,15 @@ bool PerIsolatePlatformData::FlushForegroundTasksInternal() {
409
416
// the delay is non-zero. This should not be a problem in practice.
410
417
uv_timer_start (&delayed->timer , RunForegroundTask, delay_millis, 0 );
411
418
uv_unref (reinterpret_cast <uv_handle_t *>(&delayed->timer ));
419
+ uv_handle_count_++;
412
420
413
421
scheduled_delayed_tasks_.emplace_back (delayed.release (),
414
422
[](DelayedTask* delayed) {
415
423
uv_close (reinterpret_cast <uv_handle_t *>(&delayed->timer ),
416
424
[](uv_handle_t * handle) {
417
- delete static_cast <DelayedTask*>(handle->data );
425
+ std::unique_ptr<DelayedTask> task {
426
+ static_cast <DelayedTask*>(handle->data ) };
427
+ task->platform_data ->DecreaseHandleCount ();
418
428
});
419
429
});
420
430
}
@@ -454,10 +464,6 @@ bool NodePlatform::FlushForegroundTasks(Isolate* isolate) {
454
464
return ForIsolate (isolate)->FlushForegroundTasksInternal ();
455
465
}
456
466
457
- void NodePlatform::CancelPendingDelayedTasks (Isolate* isolate) {
458
- ForIsolate (isolate)->CancelPendingDelayedTasks ();
459
- }
460
-
461
467
bool NodePlatform::IdleTasksEnabled (Isolate* isolate) { return false ; }
462
468
463
469
std::shared_ptr<v8::TaskRunner>
@@ -548,4 +554,6 @@ std::queue<std::unique_ptr<T>> TaskQueue<T>::PopAll() {
548
554
return result;
549
555
}
550
556
557
+ void MultiIsolatePlatform::CancelPendingDelayedTasks (Isolate* isolate) {}
558
+
551
559
} // namespace node
0 commit comments