diff options
author | Anna Henningsen <anna@addaleax.net> | 2019-11-19 21:34:44 +0100 |
---|---|---|
committer | Anna Henningsen <anna@addaleax.net> | 2019-11-30 02:02:50 +0100 |
commit | b7ef5937444c2693809f149acbb57457d75fe1bb (patch) | |
tree | f177e79a158dce59af8a2dbc28ad778e278e73b3 /src/node_buffer.cc | |
parent | ab2afa337979b5d26ad593b3863a900eb0c70e34 (diff) | |
download | android-node-v8-b7ef5937444c2693809f149acbb57457d75fe1bb.tar.gz android-node-v8-b7ef5937444c2693809f149acbb57457d75fe1bb.tar.bz2 android-node-v8-b7ef5937444c2693809f149acbb57457d75fe1bb.zip |
buffer: release buffers with free callbacks on env exit
Invoke the free callback for a given `Buffer` if it was created
with one, and mark the underlying `ArrayBuffer` as detached.
This makes sure that the memory is released e.g. when addons inside
Workers create such `Buffer`s.
PR-URL: https://github.com/nodejs/node/pull/30551
Reviewed-By: Gabriel Schulhof <gabriel.schulhof@intel.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Diffstat (limited to 'src/node_buffer.cc')
-rw-r--r-- | src/node_buffer.cc | 45 |
1 files changed, 36 insertions, 9 deletions
diff --git a/src/node_buffer.cc b/src/node_buffer.cc index 8641270eae..e5c4655b4c 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -53,6 +53,7 @@ using v8::Context; using v8::EscapableHandleScope; using v8::FunctionCallbackInfo; using v8::Global; +using v8::HandleScope; using v8::Int32; using v8::Integer; using v8::Isolate; @@ -73,8 +74,10 @@ namespace { class CallbackInfo { public: + ~CallbackInfo(); + static inline void Free(char* data, void* hint); - static inline CallbackInfo* New(Isolate* isolate, + static inline CallbackInfo* New(Environment* env, Local<ArrayBuffer> object, FreeCallback callback, char* data, @@ -84,9 +87,10 @@ class CallbackInfo { CallbackInfo& operator=(const CallbackInfo&) = delete; private: + static void CleanupHook(void* data); static void WeakCallback(const WeakCallbackInfo<CallbackInfo>&); inline void WeakCallback(Isolate* isolate); - inline CallbackInfo(Isolate* isolate, + inline CallbackInfo(Environment* env, Local<ArrayBuffer> object, FreeCallback callback, char* data, @@ -95,6 +99,7 @@ class CallbackInfo { FreeCallback const callback_; char* const data_; void* const hint_; + Environment* const env_; }; @@ -103,31 +108,53 @@ void CallbackInfo::Free(char* data, void*) { } -CallbackInfo* CallbackInfo::New(Isolate* isolate, +CallbackInfo* CallbackInfo::New(Environment* env, Local<ArrayBuffer> object, FreeCallback callback, char* data, void* hint) { - return new CallbackInfo(isolate, object, callback, data, hint); + return new CallbackInfo(env, object, callback, data, hint); } -CallbackInfo::CallbackInfo(Isolate* isolate, +CallbackInfo::CallbackInfo(Environment* env, Local<ArrayBuffer> object, FreeCallback callback, char* data, void* hint) - : persistent_(isolate, object), + : persistent_(env->isolate(), object), callback_(callback), data_(data), - hint_(hint) { + hint_(hint), + env_(env) { ArrayBuffer::Contents obj_c = object->GetContents(); CHECK_EQ(data_, static_cast<char*>(obj_c.Data())); if (object->ByteLength() != 0) CHECK_NOT_NULL(data_); persistent_.SetWeak(this, WeakCallback, v8::WeakCallbackType::kParameter); - isolate->AdjustAmountOfExternalAllocatedMemory(sizeof(*this)); + env->AddCleanupHook(CleanupHook, this); + env->isolate()->AdjustAmountOfExternalAllocatedMemory(sizeof(*this)); +} + + +CallbackInfo::~CallbackInfo() { + persistent_.Reset(); + env_->RemoveCleanupHook(CleanupHook, this); +} + + +void CallbackInfo::CleanupHook(void* data) { + CallbackInfo* self = static_cast<CallbackInfo*>(data); + + { + HandleScope handle_scope(self->env_->isolate()); + Local<ArrayBuffer> ab = self->persistent_.Get(self->env_->isolate()); + CHECK(!ab.IsEmpty()); + ab->Detach(); + } + + self->WeakCallback(self->env_->isolate()); } @@ -388,7 +415,7 @@ MaybeLocal<Object> New(Environment* env, } MaybeLocal<Uint8Array> ui = Buffer::New(env, ab, 0, length); - CallbackInfo::New(env->isolate(), ab, callback, data, hint); + CallbackInfo::New(env, ab, callback, data, hint); if (ui.IsEmpty()) return MaybeLocal<Object>(); |