diff options
author | legendecas <legendecas@gmail.com> | 2020-02-14 11:30:33 +0800 |
---|---|---|
committer | Shelley Vohr <shelley.vohr@gmail.com> | 2020-02-17 12:49:12 -0800 |
commit | a840e9d6395b00eb4ae0f144ee98f19ff11e85f1 (patch) | |
tree | c78c79ee0bfe42e2eeeff30d0230c47b06eee972 | |
parent | 0654e6790d9cd6f9982e07958af7fe9b95deb106 (diff) | |
download | node-new-a840e9d6395b00eb4ae0f144ee98f19ff11e85f1.tar.gz |
async_hooks: ensure event after been emitted on runInAsyncScope
The exception handler user-defined will not automatically emit after
for the async resource.
Also removes a duplicated case
`test-emit-after-uncaught-exception-runInAsyncScope.js`
which is identical to test-emit-after-uncaught-exception.js.
Refs: https://github.com/nodejs/node/pull/30965
PR-URL: https://github.com/nodejs/node/pull/31784
Fixes: https://github.com/nodejs/node/issues/31783
Reviewed-By: Vladimir de Turckheim <vlad2t@hotmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
-rw-r--r-- | lib/async_hooks.js | 15 | ||||
-rw-r--r-- | test/parallel/test-async-hooks-run-in-async-scope-caught-exception.js | 9 | ||||
-rw-r--r-- | test/parallel/test-emit-after-uncaught-exception-runInAsyncScope.js | 40 |
3 files changed, 19 insertions, 45 deletions
diff --git a/lib/async_hooks.js b/lib/async_hooks.js index 923b9d6758..3ebc9af473 100644 --- a/lib/async_hooks.js +++ b/lib/async_hooks.js @@ -22,6 +22,7 @@ const { executionAsyncId, triggerAsyncId, // Private API + hasAsyncIdStack, getHookArrays, enableHooks, disableHooks, @@ -179,12 +180,16 @@ class AsyncResource { const asyncId = this[async_id_symbol]; emitBefore(asyncId, this[trigger_async_id_symbol], this); - const ret = thisArg === undefined ? - fn(...args) : - ReflectApply(fn, thisArg, args); + try { + const ret = thisArg === undefined ? + fn(...args) : + ReflectApply(fn, thisArg, args); - emitAfter(asyncId); - return ret; + return ret; + } finally { + if (hasAsyncIdStack()) + emitAfter(asyncId); + } } emitDestroy() { diff --git a/test/parallel/test-async-hooks-run-in-async-scope-caught-exception.js b/test/parallel/test-async-hooks-run-in-async-scope-caught-exception.js new file mode 100644 index 0000000000..78e38c1e93 --- /dev/null +++ b/test/parallel/test-async-hooks-run-in-async-scope-caught-exception.js @@ -0,0 +1,9 @@ +'use strict'; + +require('../common'); +const { AsyncResource } = require('async_hooks'); + +try { + new AsyncResource('foo').runInAsyncScope(() => { throw new Error('bar'); }); +} catch {} +// Should abort (fail the case) if async id is not matching. diff --git a/test/parallel/test-emit-after-uncaught-exception-runInAsyncScope.js b/test/parallel/test-emit-after-uncaught-exception-runInAsyncScope.js deleted file mode 100644 index 5003972e99..0000000000 --- a/test/parallel/test-emit-after-uncaught-exception-runInAsyncScope.js +++ /dev/null @@ -1,40 +0,0 @@ -'use strict'; - -const common = require('../common'); -const assert = require('assert'); -const async_hooks = require('async_hooks'); - -const id_obj = {}; -let collect = true; - -const hook = async_hooks.createHook({ - before(id) { if (collect) id_obj[id] = true; }, - after(id) { delete id_obj[id]; }, -}).enable(); - -process.once('uncaughtException', common.mustCall((er) => { - assert.strictEqual(er.message, 'bye'); - collect = false; -})); - -setImmediate(common.mustCall(() => { - process.nextTick(common.mustCall(() => { - assert.strictEqual(Object.keys(id_obj).length, 0); - hook.disable(); - })); - - // Create a stack of async ids that will need to be emitted in the case of - // an uncaught exception. - const ar1 = new async_hooks.AsyncResource('Mine'); - ar1.runInAsyncScope(() => { - const ar2 = new async_hooks.AsyncResource('Mine'); - ar2.runInAsyncScope(() => { - throw new Error('bye'); - }); - }); - - // TODO(trevnorris): This test shows that the after() hooks are always called - // correctly, but it doesn't solve where the emitDestroy() is missed because - // of the uncaught exception. Simple solution is to always call emitDestroy() - // before the emitAfter(), but how to codify this? -})); |