Skip to content

Commit e51b8c3

Browse files
committed
async_hooks: enabledHooksExist shall return if hooks are enabled
Correct the implementaton of enabledHooksExist to return true if there are enabled hooks. Adapt callsites which used getHooksArrays() as workaround.
1 parent 28f468a commit e51b8c3

File tree

8 files changed

+32
-18
lines changed

8 files changed

+32
-18
lines changed

lib/async_hooks.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ const {
5252
emitBefore,
5353
emitAfter,
5454
emitDestroy,
55-
enabledHooksExist,
5655
initHooksExist,
5756
destroyHooksExist,
5857
} = internal_async_hooks;
@@ -188,7 +187,7 @@ class AsyncResource {
188187
this[trigger_async_id_symbol] = triggerAsyncId;
189188

190189
if (initHooksExist()) {
191-
if (enabledHooksExist() && type.length === 0) {
190+
if (type.length === 0) {
192191
throw new ERR_ASYNC_TYPE(type);
193192
}
194193

lib/internal/async_hooks.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ function hasHooks(key) {
481481
}
482482

483483
function enabledHooksExist() {
484-
return hasHooks(kCheck);
484+
return active_hooks.array.length > 0;
485485
}
486486

487487
function initHooksExist() {
@@ -563,7 +563,7 @@ function popAsyncContext(asyncId) {
563563
const stackLength = async_hook_fields[kStackLength];
564564
if (stackLength === 0) return false;
565565

566-
if (enabledHooksExist() && async_id_fields[kExecutionAsyncId] !== asyncId) {
566+
if (async_hook_fields[kCheck] > 0 && async_id_fields[kExecutionAsyncId] !== asyncId) {
567567
// Do the same thing as the native code (i.e. crash hard).
568568
return popAsyncContext_(asyncId);
569569
}

lib/internal/streams/end-of-stream.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ const {
4545
kIsClosedPromise,
4646
} = require('internal/streams/utils');
4747

48-
const { getHookArrays } = require('internal/async_hooks');
48+
const { enabledHooksExist } = require('internal/async_hooks');
4949
const AsyncContextFrame = require('internal/async_context_frame');
5050

5151
// Lazy load
@@ -78,8 +78,7 @@ function eos(stream, options, callback) {
7878
validateFunction(callback, 'callback');
7979
validateAbortSignal(options.signal, 'options.signal');
8080

81-
if (AsyncContextFrame.current() ||
82-
getHookArrays()[0].length > 0) {
81+
if (AsyncContextFrame.current() || enabledHooksExist()) {
8382
// Avoid AsyncResource.bind() because it calls ObjectDefineProperties which
8483
// is a bottleneck here.
8584
callback = once(bindAsyncResource(callback, 'STREAM_END_OF_STREAM'));

src/env.cc

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,7 @@ void AsyncHooks::push_async_context(
127127
std::variant<Local<Object>*, Global<Object>*> resource) {
128128
std::visit([](auto* ptr) { CHECK_IMPLIES(ptr != nullptr, !ptr->IsEmpty()); },
129129
resource);
130-
// Since async_hooks is experimental, do only perform the check
131-
// when async_hooks is enabled.
130+
132131
if (fields_[kCheck] > 0) {
133132
CHECK_GE(async_id, -1);
134133
CHECK_GE(trigger_async_id, -1);
@@ -1756,7 +1755,7 @@ AsyncHooks::AsyncHooks(Isolate* isolate, const SerializeInfo* info)
17561755
clear_async_id_stack();
17571756

17581757
// Always perform async_hooks checks, not just when async_hooks is enabled.
1759-
// TODO(AndreasMadsen): Consider removing this for LTS releases.
1758+
// Can be disabled via CLI option --no-force-async-hooks-checks
17601759
// See discussion in https://github.com/nodejs/node/pull/15454
17611760
// When removing this, do it by reverting the commit. Otherwise the test
17621761
// and flag changes won't be included.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Flags: --expose-internals
2+
'use strict';
3+
4+
require('../common');
5+
const assert = require('assert');
6+
const { createHook } = require('async_hooks');
7+
const { enabledHooksExist } = require('internal/async_hooks');
8+
9+
assert.strictEqual(enabledHooksExist(), false);
10+
11+
const ah = createHook({});
12+
assert.strictEqual(enabledHooksExist(), false);
13+
14+
ah.enable();
15+
assert.strictEqual(enabledHooksExist(), true);
16+
17+
ah.disable();
18+
assert.strictEqual(enabledHooksExist(), false);

test/parallel/test-stream-finished-async-local-storage.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const { Readable, finished } = require('stream');
66
const { AsyncLocalStorage } = require('async_hooks');
77
const assert = require('assert');
88
const AsyncContextFrame = require('internal/async_context_frame');
9-
const internalAsyncHooks = require('internal/async_hooks');
9+
const { enabledHooksExist } = require('internal/async_hooks');
1010

1111
// This test verifies that ALS context is preserved when using stream.finished()
1212

@@ -15,8 +15,7 @@ const readable = new Readable();
1515

1616
als.run('test-context-1', common.mustCall(() => {
1717
finished(readable, common.mustCall(() => {
18-
assert.strictEqual(AsyncContextFrame.enabled || internalAsyncHooks.getHookArrays()[0].length > 0,
19-
true);
18+
assert.strictEqual(AsyncContextFrame.enabled || enabledHooksExist(), true);
2019
assert.strictEqual(als.getStore(), 'test-context-1');
2120
}));
2221
}));

test/parallel/test-stream-finished-bindAsyncResource-path.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const common = require('../common');
55
const { Readable, finished } = require('stream');
66
const { createHook, executionAsyncId } = require('async_hooks');
77
const assert = require('assert');
8-
const internalAsyncHooks = require('internal/async_hooks');
8+
const { enabledHooksExist } = require('internal/async_hooks');
99

1010
// This test verifies that when there are active async hooks, stream.finished() uses
1111
// the bindAsyncResource path
@@ -27,7 +27,7 @@ const readable = new Readable();
2727
finished(readable, common.mustCall(() => {
2828
const currentAsyncId = executionAsyncId();
2929
const ctx = contextMap.get(currentAsyncId);
30-
assert.strictEqual(internalAsyncHooks.getHookArrays()[0].length > 0, true);
30+
assert.ok(enabledHooksExist());
3131
assert.strictEqual(ctx, 'abc-123');
3232
}));
3333

test/parallel/test-stream-finished-default-path.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@ const common = require('../common');
55
const { Readable, finished } = require('stream');
66
const assert = require('assert');
77
const AsyncContextFrame = require('internal/async_context_frame');
8-
const internalAsyncHooks = require('internal/async_hooks');
8+
const { enabledHooksExist } = require('internal/async_hooks');
99

1010
// This test verifies that when there are no active async hooks, stream.finished() uses the default callback path
1111

1212
const readable = new Readable();
1313

1414
finished(readable, common.mustCall(() => {
15-
assert.strictEqual(internalAsyncHooks.getHookArrays()[0].length === 0, true);
15+
assert.strictEqual(enabledHooksExist(), false);
1616
assert.strictEqual(
17-
AsyncContextFrame.current() || internalAsyncHooks.getHookArrays()[0].length > 0,
17+
AsyncContextFrame.current() || enabledHooksExist(),
1818
false,
1919
);
2020
}));

0 commit comments

Comments
 (0)