diff options
author | Ulan Degenbaev <ulan@chromium.org> | 2018-04-12 22:01:11 +0200 |
---|---|---|
committer | Anatoli Papirovski <apapirovski@mac.com> | 2018-04-25 10:40:16 +0200 |
commit | d3edf2fcde0c37206dc339aab7333212d20aa0f1 (patch) | |
tree | faf96de3d8b841f6dda9f7b0a049c67289862659 /src/node_platform.cc | |
parent | 95197ed2b052b1fee312cfc127a9f67844dd77b7 (diff) | |
download | android-node-v8-d3edf2fcde0c37206dc339aab7333212d20aa0f1.tar.gz android-node-v8-d3edf2fcde0c37206dc339aab7333212d20aa0f1.tar.bz2 android-node-v8-d3edf2fcde0c37206dc339aab7333212d20aa0f1.zip |
src: limit foreground tasks draining loop
Foreground tasks that repost themselves can force the draining loop
to run indefinitely long without giving other tasks chance to run.
This limits the foreground task draining loop to run only the tasks
that were in the tasks queue at the beginning of the loop.
PR-URL: https://github.com/nodejs/node/pull/19987
Fixes: https://github.com/nodejs/node/issues/19937
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Yang Guo <yangguo@chromium.org>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Reviewed-By: Khaidi Chu <i@2333.moe>
Diffstat (limited to 'src/node_platform.cc')
-rw-r--r-- | src/node_platform.cc | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/src/node_platform.cc b/src/node_platform.cc index d96db08692..b8f1344727 100644 --- a/src/node_platform.cc +++ b/src/node_platform.cc @@ -95,7 +95,7 @@ void PerIsolatePlatformData::PostDelayedTask( } PerIsolatePlatformData::~PerIsolatePlatformData() { - FlushForegroundTasksInternal(); + while (FlushForegroundTasksInternal()) {} CancelPendingDelayedTasks(); uv_close(reinterpret_cast<uv_handle_t*>(flush_tasks_), @@ -223,7 +223,13 @@ bool PerIsolatePlatformData::FlushForegroundTasksInternal() { }); }); } - while (std::unique_ptr<Task> task = foreground_tasks_.Pop()) { + // Move all foreground tasks into a separate queue and flush that queue. + // This way tasks that are posted while flushing the queue will be run on the + // next call of FlushForegroundTasksInternal. + std::queue<std::unique_ptr<Task>> tasks = foreground_tasks_.PopAll(); + while (!tasks.empty()) { + std::unique_ptr<Task> task = std::move(tasks.front()); + tasks.pop(); did_work = true; RunForegroundTask(std::move(task)); } @@ -254,8 +260,8 @@ void NodePlatform::CallDelayedOnForegroundThread(Isolate* isolate, std::unique_ptr<Task>(task), delay_in_seconds); } -void NodePlatform::FlushForegroundTasks(v8::Isolate* isolate) { - ForIsolate(isolate)->FlushForegroundTasksInternal(); +bool NodePlatform::FlushForegroundTasks(v8::Isolate* isolate) { + return ForIsolate(isolate)->FlushForegroundTasksInternal(); } void NodePlatform::CancelPendingDelayedTasks(v8::Isolate* isolate) { @@ -348,4 +354,12 @@ void TaskQueue<T>::Stop() { tasks_available_.Broadcast(scoped_lock); } +template <class T> +std::queue<std::unique_ptr<T>> TaskQueue<T>::PopAll() { + Mutex::ScopedLock scoped_lock(lock_); + std::queue<std::unique_ptr<T>> result; + result.swap(task_queue_); + return result; +} + } // namespace node |