Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnatoli Papirovski <apapirovski@mac.com>2018-01-19 00:52:51 +0300
committerAnatoli Papirovski <apapirovski@mac.com>2018-01-21 20:39:41 +0300
commit8803b69c724e7b03ec0fc4c82b71575262487624 (patch)
tree4e7b737d45ada0a40c2d142a9fd44a26270335ba /src/async_wrap.cc
parentd62566e1b1bb4734635d51d53c16f6efa3a7f5b5 (diff)
async_wrap: schedule destroy hook as unref
Since the `DestroyAsyncIdsCallback` in Node.js can be scheduled as a result of GC, that means that it can accidentally keep the event loop open when it shouldn't. Replace `SetImmediate` with the newly introduced `SetUnrefImmediate` and in addition introduce RunBeforeExit callbacks, of which `DestroyAsyncIdsCallback` is now the first. These callbacks will run before the `beforeExit` event is emitted (which will now only be emitted if the event loop is still not active). PR-URL: https://github.com/nodejs/node/pull/18241 Fixes: https://github.com/nodejs/node/issues/18190 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Andreas Madsen <amwebdk@gmail.com>
Diffstat (limited to 'src/async_wrap.cc')
-rw-r--r--src/async_wrap.cc10
1 files changed, 9 insertions, 1 deletions
diff --git a/src/async_wrap.cc b/src/async_wrap.cc
index f770348b9c9..5258674ff33 100644
--- a/src/async_wrap.cc
+++ b/src/async_wrap.cc
@@ -159,6 +159,12 @@ static void DestroyAsyncIdsCallback(Environment* env, void* data) {
} while (!env->destroy_async_id_list()->empty());
}
+static void DestroyAsyncIdsCallback(void* arg) {
+ Environment* env = static_cast<Environment*>(arg);
+ if (!env->destroy_async_id_list()->empty())
+ DestroyAsyncIdsCallback(env, nullptr);
+}
+
void AsyncWrap::EmitPromiseResolve(Environment* env, double async_id) {
AsyncHooks* async_hooks = env->async_hooks();
@@ -502,6 +508,8 @@ void AsyncWrap::Initialize(Local<Object> target,
Isolate* isolate = env->isolate();
HandleScope scope(isolate);
+ env->BeforeExit(DestroyAsyncIdsCallback, env);
+
env->SetMethod(target, "setupHooks", SetupHooks);
env->SetMethod(target, "pushAsyncIds", PushAsyncIds);
env->SetMethod(target, "popAsyncIds", PopAsyncIds);
@@ -663,7 +671,7 @@ void AsyncWrap::EmitDestroy(Environment* env, double async_id) {
return;
if (env->destroy_async_id_list()->empty()) {
- env->SetImmediate(DestroyAsyncIdsCallback, nullptr);
+ env->SetUnrefImmediate(DestroyAsyncIdsCallback, nullptr);
}
env->destroy_async_id_list()->push_back(async_id);