summaryrefslogtreecommitdiff
path: root/src/node_buffer.cc
diff options
context:
space:
mode:
authorAnna Henningsen <anna@addaleax.net>2019-11-19 21:34:44 +0100
committerAnna Henningsen <anna@addaleax.net>2019-11-30 02:02:50 +0100
commitb7ef5937444c2693809f149acbb57457d75fe1bb (patch)
treef177e79a158dce59af8a2dbc28ad778e278e73b3 /src/node_buffer.cc
parentab2afa337979b5d26ad593b3863a900eb0c70e34 (diff)
downloadandroid-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.cc45
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>();