Skip to content

Commit

Permalink
async_hooks: executionAsyncResource matches in hooks
Browse files Browse the repository at this point in the history
Ensure that resource returned by executionAsyncResource() in before
and after hook matches that resource causing this before/after calls.

PR-URL: nodejs#31821
Refs: nodejs#30959
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Minwoo Jung <nodecorelab@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: Vladimir de Turckheim <vlad2t@hotmail.com>
  • Loading branch information
Flarna authored and puzpuzpuz committed Apr 14, 2020
1 parent 8752332 commit 1f61d3c
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 9 deletions.
18 changes: 9 additions & 9 deletions src/api/callback.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,16 @@ InternalCallbackScope::InternalCallbackScope(Environment* env,
// If you hit this assertion, you forgot to enter the v8::Context first.
CHECK_EQ(Environment::GetCurrent(env->isolate()), env);

env->async_hooks()->push_async_context(
async_context_.async_id, async_context_.trigger_async_id, object);

pushed_ids_ = true;

if (asyncContext.async_id != 0 && !skip_hooks_) {
// No need to check a return value because the application will exit if
// an exception occurs.
AsyncWrap::EmitBefore(env, asyncContext.async_id);
}

env->async_hooks()->push_async_context(async_context_.async_id,
async_context_.trigger_async_id, object);

pushed_ids_ = true;
}

InternalCallbackScope::~InternalCallbackScope() {
Expand All @@ -88,15 +88,15 @@ void InternalCallbackScope::Close() {
env_->async_hooks()->clear_async_id_stack();
}

if (!failed_ && async_context_.async_id != 0 && !skip_hooks_) {
AsyncWrap::EmitAfter(env_, async_context_.async_id);
}

if (pushed_ids_)
env_->async_hooks()->pop_async_context(async_context_.async_id);

if (failed_) return;

if (async_context_.async_id != 0 && !skip_hooks_) {
AsyncWrap::EmitAfter(env_, async_context_.async_id);
}

if (env_->async_callback_scope_depth() > 1 || skip_task_queues_) {
return;
}
Expand Down
62 changes: 62 additions & 0 deletions test/async-hooks/test-async-exec-resource-match.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
'use strict';

const common = require('../common');
const assert = require('assert');
const { readFile } = require('fs');
const {
createHook,
executionAsyncResource,
AsyncResource
} = require('async_hooks');

// Ignore any asyncIds created before our hook is active.
let firstSeenAsyncId = -1;
const idResMap = new Map();
const numExpectedCalls = 5;

createHook({
init: common.mustCallAtLeast(
(asyncId, type, triggerId, resource) => {
if (firstSeenAsyncId === -1) {
firstSeenAsyncId = asyncId;
}
assert.ok(idResMap.get(asyncId) === undefined);
idResMap.set(asyncId, resource);
}, numExpectedCalls),
before(asyncId) {
if (asyncId >= firstSeenAsyncId) {
beforeHook(asyncId);
}
},
after(asyncId) {
if (asyncId >= firstSeenAsyncId) {
afterHook(asyncId);
}
}
}).enable();

const beforeHook = common.mustCallAtLeast(
(asyncId) => {
const res = idResMap.get(asyncId);
assert.ok(res !== undefined);
const execRes = executionAsyncResource();
assert.ok(execRes === res, 'resource mismatch in before');
}, numExpectedCalls);

const afterHook = common.mustCallAtLeast(
(asyncId) => {
const res = idResMap.get(asyncId);
assert.ok(res !== undefined);
const execRes = executionAsyncResource();
assert.ok(execRes === res, 'resource mismatch in after');
}, numExpectedCalls);

const res = new AsyncResource('TheResource');
const initRes = idResMap.get(res.asyncId());
assert.ok(initRes === res, 'resource mismatch in init');
res.runInAsyncScope(common.mustCall(() => {
const execRes = executionAsyncResource();
assert.ok(execRes === res, 'resource mismatch in cb');
}));

readFile(__filename, common.mustCall());

0 comments on commit 1f61d3c

Please sign in to comment.