diff options
author | Sebastian Mayr <git@smayr.name> | 2017-11-09 22:57:04 +0100 |
---|---|---|
committer | Anna Henningsen <anna@addaleax.net> | 2017-11-16 19:58:00 +0100 |
commit | 22901d81c905873486de676c8ca9d13f11503878 (patch) | |
tree | 7a67a0c003122c99d687219b6e0a39370f2160ac /src | |
parent | b3127cd537a62fd02a639333193dde5741ac3a68 (diff) | |
download | android-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.cc | 41 | ||||
-rw-r--r-- | src/async-wrap.h | 3 | ||||
-rw-r--r-- | src/env.h | 1 |
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; @@ -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") \ |