Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 4458378

Browse filesBrowse files
addaleaxtargos
authored andcommitted
async_hooks: only emit after for AsyncResource if stack not empty
We clear the async id stack inside the uncaught exception handler and emit `after` events in the process, so we should not emit `after` a second time from the `runInAsyncScope()` code. This should match the behaviour we have in C++. Fixes: #30080 PR-URL: #30087 Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: Anto Aravinth <anto.aravinth.cse@gmail.com>
1 parent 93b1bb8 commit 4458378
Copy full SHA for 4458378

File tree

Expand file treeCollapse file tree

2 files changed

+39
-1
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

2 files changed

+39
-1
lines changed
Open diff view settings
Collapse file

‎lib/async_hooks.js‎

Copy file name to clipboardExpand all lines: lib/async_hooks.js
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const {
1717
executionAsyncId,
1818
triggerAsyncId,
1919
// Private API
20+
hasAsyncIdStack,
2021
getHookArrays,
2122
enableHooks,
2223
disableHooks,
@@ -172,7 +173,8 @@ class AsyncResource {
172173
return fn(...args);
173174
return Reflect.apply(fn, thisArg, args);
174175
} finally {
175-
emitAfter(asyncId);
176+
if (hasAsyncIdStack())
177+
emitAfter(asyncId);
176178
}
177179
}
178180

Collapse file
+36Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
'use strict';
2+
const common = require('../common');
3+
const assert = require('assert');
4+
const async_hooks = require('async_hooks');
5+
6+
// Regression test for https://github.com/nodejs/node/issues/30080:
7+
// An uncaught exception inside a queueMicrotask callback should not lead
8+
// to multiple after() calls for it.
9+
10+
let µtaskId;
11+
const events = [];
12+
13+
async_hooks.createHook({
14+
init(id, type, triggerId, resoure) {
15+
if (type === 'Microtask') {
16+
µtaskId = id;
17+
events.push('init');
18+
}
19+
},
20+
before(id) {
21+
if (id === µtaskId) events.push('before');
22+
},
23+
after(id) {
24+
if (id === µtaskId) events.push('after');
25+
},
26+
destroy(id) {
27+
if (id === µtaskId) events.push('destroy');
28+
}
29+
}).enable();
30+
31+
queueMicrotask(() => { throw new Error(); });
32+
33+
process.on('uncaughtException', common.mustCall());
34+
process.on('exit', () => {
35+
assert.deepStrictEqual(events, ['init', 'after', 'before', 'destroy']);
36+
});

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.