summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSebastian Mayr <git@smayr.name>2017-11-09 22:57:04 +0100
committerAnna Henningsen <anna@addaleax.net>2017-11-16 19:58:00 +0100
commit22901d81c905873486de676c8ca9d13f11503878 (patch)
tree7a67a0c003122c99d687219b6e0a39370f2160ac /src
parentb3127cd537a62fd02a639333193dde5741ac3a68 (diff)
downloadandroid-node-v8-22901d81c905873486de676c8ca9d13f11503878.tar.gz
android-node-v8-22901d81c905873486de676c8ca9d13f11503878.tar.bz2
android-node-v8-22901d81c905873486de676c8ca9d13f11503878.zip
async_hooks: add destroy event for gced AsyncResources
In cases where libraries create AsyncResources which may be emitting more events depending on usage, the only way to ensure that destroy is called properly is by calling it when the resource gets garbage collected. Fixes: https://github.com/nodejs/node/issues/16153 PR-URL: https://github.com/nodejs/node/pull/16998 Fixes: https://github.com/nodejs/node/issues/16153 Reviewed-By: Andreas Madsen <amwebdk@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/async-wrap.cc41
-rw-r--r--src/async-wrap.h3
-rw-r--r--src/env.h1
3 files changed, 45 insertions, 0 deletions
diff --git a/src/async-wrap.cc b/src/async-wrap.cc
index c53929d11b..75af5c1a08 100644
--- a/src/async-wrap.cc
+++ b/src/async-wrap.cc
@@ -427,6 +427,46 @@ static void DisablePromiseHook(const FunctionCallbackInfo<Value>& args) {
}
+class DestroyParam {
+ public:
+ double asyncId;
+ v8::Persistent<Object> target;
+ v8::Persistent<Object> propBag;
+};
+
+
+void AsyncWrap::WeakCallback(const v8::WeakCallbackInfo<DestroyParam>& info) {
+ HandleScope scope(info.GetIsolate());
+
+ Environment* env = Environment::GetCurrent(info.GetIsolate());
+ DestroyParam* p = info.GetParameter();
+ Local<Object> prop_bag = PersistentToLocal(info.GetIsolate(), p->propBag);
+
+ Local<Value> val = prop_bag->Get(env->destroyed_string());
+ if (val->IsFalse()) {
+ AsyncWrap::EmitDestroy(env, p->asyncId);
+ }
+ p->target.Reset();
+ p->propBag.Reset();
+ delete p;
+}
+
+
+static void RegisterDestroyHook(const FunctionCallbackInfo<Value>& args) {
+ CHECK(args[0]->IsObject());
+ CHECK(args[1]->IsNumber());
+ CHECK(args[2]->IsObject());
+
+ Isolate* isolate = args.GetIsolate();
+ DestroyParam* p = new DestroyParam();
+ p->asyncId = args[1].As<Number>()->Value();
+ p->target.Reset(isolate, args[0].As<Object>());
+ p->propBag.Reset(isolate, args[2].As<Object>());
+ p->target.SetWeak(
+ p, AsyncWrap::WeakCallback, v8::WeakCallbackType::kParameter);
+}
+
+
void AsyncWrap::GetAsyncId(const FunctionCallbackInfo<Value>& args) {
AsyncWrap* wrap;
args.GetReturnValue().Set(-1);
@@ -502,6 +542,7 @@ void AsyncWrap::Initialize(Local<Object> target,
env->SetMethod(target, "queueDestroyAsyncId", QueueDestroyAsyncId);
env->SetMethod(target, "enablePromiseHook", EnablePromiseHook);
env->SetMethod(target, "disablePromiseHook", DisablePromiseHook);
+ env->SetMethod(target, "registerDestroyHook", RegisterDestroyHook);
v8::PropertyAttribute ReadOnlyDontDelete =
static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete);
diff --git a/src/async-wrap.h b/src/async-wrap.h
index 39b6f287c9..222cda1fd7 100644
--- a/src/async-wrap.h
+++ b/src/async-wrap.h
@@ -84,6 +84,7 @@ namespace node {
NODE_ASYNC_INSPECTOR_PROVIDER_TYPES(V)
class Environment;
+class DestroyParam;
class AsyncWrap : public BaseObject {
public:
@@ -163,6 +164,8 @@ class AsyncWrap : public BaseObject {
virtual size_t self_size() const = 0;
+ static void WeakCallback(const v8::WeakCallbackInfo<DestroyParam> &info);
+
private:
friend class PromiseWrap;
diff --git a/src/env.h b/src/env.h
index e37dcf17ae..75bc210cfb 100644
--- a/src/env.h
+++ b/src/env.h
@@ -120,6 +120,7 @@ class ModuleWrap;
V(cwd_string, "cwd") \
V(dest_string, "dest") \
V(destroy_string, "destroy") \
+ V(destroyed_string, "destroyed") \
V(detached_string, "detached") \
V(dns_a_string, "A") \
V(dns_aaaa_string, "AAAA") \