diff options
author | Anna Henningsen <anna@addaleax.net> | 2017-09-15 16:03:48 +0300 |
---|---|---|
committer | Anna Henningsen <anna@addaleax.net> | 2017-09-21 03:03:02 +0300 |
commit | f27b5e4bdaafc73a830a0451ee3c641b8bcd08fe (patch) | |
tree | 09e8fccc815d2a27db433ce233e80bbcbeb0579a /src/node_platform.cc | |
parent | 01c680b92aed62e128aa2abd4ad923f9a6a0331a (diff) |
src: prepare platform for upstream V8 changes
V8 platform tasks may schedule other tasks (both background and
foreground), and may perform asynchronous operations like
resolving Promises.
To address that:
- Run the task queue drain call inside a callback scope.
This makes sure asynchronous operations inside it, like
resolving promises, lead to the microtask queue and any
subsequent operations not being silently forgotten.
- Move the task queue drain call before `EmitBeforeExit()`
and only run `EmitBeforeExit()` if there is no new event
loop work.
- Account for possible new foreground tasks scheduled by
background tasks in `DrainBackgroundTasks()`.
PR-URL: https://github.com/nodejs/node/pull/15428
Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Matthew Loring <mattloring@google.com>
Diffstat (limited to 'src/node_platform.cc')
-rw-r--r-- | src/node_platform.cc | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/src/node_platform.cc b/src/node_platform.cc index 3d023114ad2..320136c3f72 100644 --- a/src/node_platform.cc +++ b/src/node_platform.cc @@ -1,10 +1,14 @@ #include "node_platform.h" +#include "node_internals.h" #include "util.h" namespace node { +using v8::HandleScope; using v8::Isolate; +using v8::Local; +using v8::Object; using v8::Platform; using v8::Task; using v8::TracingController; @@ -63,22 +67,33 @@ size_t NodePlatform::NumberOfAvailableBackgroundThreads() { return threads_.size(); } -static void RunForegroundTask(uv_timer_t* handle) { - Task* task = static_cast<Task*>(handle->data); +static void RunForegroundTask(Task* task) { + Isolate* isolate = Isolate::GetCurrent(); + HandleScope scope(isolate); + Environment* env = Environment::GetCurrent(isolate); + InternalCallbackScope cb_scope(env, Local<Object>(), { 0, 0 }, + InternalCallbackScope::kAllowEmptyResource); task->Run(); delete task; +} + +static void RunForegroundTask(uv_timer_t* handle) { + Task* task = static_cast<Task*>(handle->data); + RunForegroundTask(task); uv_close(reinterpret_cast<uv_handle_t*>(handle), [](uv_handle_t* handle) { delete reinterpret_cast<uv_timer_t*>(handle); }); } void NodePlatform::DrainBackgroundTasks() { - FlushForegroundTasksInternal(); - background_tasks_.BlockingDrain(); + while (FlushForegroundTasksInternal()) + background_tasks_.BlockingDrain(); } -void NodePlatform::FlushForegroundTasksInternal() { +bool NodePlatform::FlushForegroundTasksInternal() { + bool did_work = false; while (auto delayed = foreground_delayed_tasks_.Pop()) { + did_work = true; uint64_t delay_millis = static_cast<uint64_t>(delayed->second + 0.5) * 1000; uv_timer_t* handle = new uv_timer_t(); @@ -91,9 +106,10 @@ void NodePlatform::FlushForegroundTasksInternal() { delete delayed; } while (Task* task = foreground_tasks_.Pop()) { - task->Run(); - delete task; + did_work = true; + RunForegroundTask(task); } + return did_work; } void NodePlatform::CallOnBackgroundThread(Task* task, |