Skip to content

Commit 19fbe32

Browse files
committedFeb 26, 2020
async_hooks: executionAsyncResource matches in hooks
Ensure that resource returned by executionAsyncResource() in before and after hook matches that resource causing this before/after calls.
1 parent fb73045 commit 19fbe32

File tree

2 files changed

+71
-9
lines changed

2 files changed

+71
-9
lines changed
 

‎src/api/callback.cc

+9-9
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,16 @@ InternalCallbackScope::InternalCallbackScope(Environment* env,
6262
// If you hit this assertion, you forgot to enter the v8::Context first.
6363
CHECK_EQ(Environment::GetCurrent(env->isolate()), env);
6464

65+
env->async_hooks()->push_async_context(
66+
async_context_.async_id, async_context_.trigger_async_id, object);
67+
68+
pushed_ids_ = true;
69+
6570
if (asyncContext.async_id != 0 && !skip_hooks_) {
6671
// No need to check a return value because the application will exit if
6772
// an exception occurs.
6873
AsyncWrap::EmitBefore(env, asyncContext.async_id);
6974
}
70-
71-
env->async_hooks()->push_async_context(async_context_.async_id,
72-
async_context_.trigger_async_id, object);
73-
74-
pushed_ids_ = true;
7575
}
7676

7777
InternalCallbackScope::~InternalCallbackScope() {
@@ -88,15 +88,15 @@ void InternalCallbackScope::Close() {
8888
env_->async_hooks()->clear_async_id_stack();
8989
}
9090

91+
if (!failed_ && async_context_.async_id != 0 && !skip_hooks_) {
92+
AsyncWrap::EmitAfter(env_, async_context_.async_id);
93+
}
94+
9195
if (pushed_ids_)
9296
env_->async_hooks()->pop_async_context(async_context_.async_id);
9397

9498
if (failed_) return;
9599

96-
if (async_context_.async_id != 0 && !skip_hooks_) {
97-
AsyncWrap::EmitAfter(env_, async_context_.async_id);
98-
}
99-
100100
if (env_->async_callback_scope_depth() > 1 || skip_task_queues_) {
101101
return;
102102
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('assert');
5+
const { readFile } = require('fs');
6+
const {
7+
createHook,
8+
executionAsyncResource,
9+
AsyncResource
10+
} = require('async_hooks');
11+
12+
// Ignore any asyncIds created before our hook is active.
13+
let firstSeenAsyncId = -1;
14+
const idResMap = new Map();
15+
const numExpectedCalls = 5;
16+
17+
createHook({
18+
init: common.mustCallAtLeast(
19+
(asyncId, type, triggerId, resource) => {
20+
if (firstSeenAsyncId === -1) {
21+
firstSeenAsyncId = asyncId;
22+
}
23+
assert.ok(idResMap.get(asyncId) === undefined);
24+
idResMap.set(asyncId, resource);
25+
}, numExpectedCalls),
26+
before(asyncId) {
27+
if (asyncId >= firstSeenAsyncId) {
28+
beforeHook(asyncId);
29+
}
30+
},
31+
after(asyncId) {
32+
if (asyncId >= firstSeenAsyncId) {
33+
afterHook(asyncId);
34+
}
35+
}
36+
}).enable();
37+
38+
const beforeHook = common.mustCallAtLeast(
39+
(asyncId) => {
40+
const res = idResMap.get(asyncId);
41+
assert.ok(res !== undefined);
42+
const execRes = executionAsyncResource();
43+
assert.ok(execRes === res, 'resource mismatch in before');
44+
}, numExpectedCalls);
45+
46+
const afterHook = common.mustCallAtLeast(
47+
(asyncId) => {
48+
const res = idResMap.get(asyncId);
49+
assert.ok(res !== undefined);
50+
const execRes = executionAsyncResource();
51+
assert.ok(execRes === res, 'resource mismatch in after');
52+
}, numExpectedCalls);
53+
54+
const res = new AsyncResource('TheResource');
55+
const initRes = idResMap.get(res.asyncId());
56+
assert.ok(initRes === res, 'resource mismatch in init');
57+
res.runInAsyncScope(common.mustCall(() => {
58+
const execRes = executionAsyncResource();
59+
assert.ok(execRes === res, 'resource mismatch in cb');
60+
}));
61+
62+
readFile(__filename, common.mustCall());

0 commit comments

Comments
 (0)