Skip to content

Commit b663d2b

Browse files
trevnorrisrvagg
authored andcommitted
async_wrap: call callback in destructor
Call a user's callback to notify that the handle has been destroyed. Only pass the id of the AsyncWrap instance since the object no longer exists. The object that's being destructed should never be inspected within the callback or any time afterward. This commit make a breaking change. The init callback will now be passed arguments in the order of provider, id, parent. PR-URL: #3461 Reviewed-By: Fedor Indutny <[email protected]>
1 parent eccbec9 commit b663d2b

6 files changed

+25
-4
lines changed

src/async-wrap-inl.h

+18-1
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,12 @@ inline AsyncWrap::AsyncWrap(Environment* env,
4141

4242
v8::Local<v8::Value> argv[] = {
4343
v8::Int32::New(env->isolate(), provider),
44+
v8::Integer::New(env->isolate(), get_uid()),
4445
Null(env->isolate())
4546
};
4647

4748
if (parent != nullptr)
48-
argv[1] = parent->object();
49+
argv[2] = parent->object();
4950

5051
v8::MaybeLocal<v8::Value> ret =
5152
init_fn->Call(env->context(), object, ARRAY_SIZE(argv), argv);
@@ -57,6 +58,22 @@ inline AsyncWrap::AsyncWrap(Environment* env,
5758
}
5859

5960

61+
inline AsyncWrap::~AsyncWrap() {
62+
if (!ran_init_callback())
63+
return;
64+
65+
v8::Local<v8::Function> fn = env()->async_hooks_destroy_function();
66+
if (!fn.IsEmpty()) {
67+
v8::HandleScope scope(env()->isolate());
68+
v8::Local<v8::Value> uid = v8::Integer::New(env()->isolate(), get_uid());
69+
v8::MaybeLocal<v8::Value> ret =
70+
fn->Call(env()->context(), v8::Null(env()->isolate()), 1, &uid);
71+
if (ret.IsEmpty())
72+
FatalError("node::AsyncWrap::~AsyncWrap", "destroy hook threw");
73+
}
74+
}
75+
76+
6077
inline bool AsyncWrap::ran_init_callback() const {
6178
return static_cast<bool>(bits_ & 1);
6279
}

src/async-wrap.cc

+3
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ static void SetupHooks(const FunctionCallbackInfo<Value>& args) {
131131
env->set_async_hooks_pre_function(args[1].As<Function>());
132132
if (args[2]->IsFunction())
133133
env->set_async_hooks_post_function(args[2].As<Function>());
134+
if (args[3]->IsFunction())
135+
env->set_async_hooks_destroy_function(args[3].As<Function>());
134136
}
135137

136138

@@ -156,6 +158,7 @@ static void Initialize(Local<Object> target,
156158
env->set_async_hooks_init_function(Local<Function>());
157159
env->set_async_hooks_pre_function(Local<Function>());
158160
env->set_async_hooks_post_function(Local<Function>());
161+
env->set_async_hooks_destroy_function(Local<Function>());
159162
}
160163

161164

src/async-wrap.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class AsyncWrap : public BaseObject {
5151
ProviderType provider,
5252
AsyncWrap* parent = nullptr);
5353

54-
inline virtual ~AsyncWrap() override = default;
54+
inline virtual ~AsyncWrap();
5555

5656
inline ProviderType provider_type() const;
5757

src/env.h

+1
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ namespace node {
236236
V(async_hooks_init_function, v8::Function) \
237237
V(async_hooks_pre_function, v8::Function) \
238238
V(async_hooks_post_function, v8::Function) \
239+
V(async_hooks_destroy_function, v8::Function) \
239240
V(binding_cache_object, v8::Object) \
240241
V(buffer_constructor_function, v8::Function) \
241242
V(buffer_prototype_object, v8::Object) \

test/parallel/test-async-wrap-disabled-propagate-parent.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ let cntr = 0;
1010
let server;
1111
let client;
1212

13-
function init(type, parent) {
13+
function init(type, id, parent) {
1414
if (parent) {
1515
cntr++;
1616
// Cannot assert in init callback or will abort.

test/parallel/test-async-wrap-propagate-parent.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ let cntr = 0;
99
let server;
1010
let client;
1111

12-
function init(type, parent) {
12+
function init(type, id, parent) {
1313
if (parent) {
1414
cntr++;
1515
// Cannot assert in init callback or will abort.

0 commit comments

Comments
 (0)