-
Notifications
You must be signed in to change notification settings - Fork 29.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
async_hooks: emitAfter correctly on fatalException #14914
Conversation
// Emit the after() hooks now that the exception has been handled. | ||
if (async_hook_fields[kAfter] > 0) { | ||
do { | ||
NativeModule.require('async_hooks').emitAfter( | ||
async_uid_fields[kCurrentAsyncId]); | ||
// popAsyncIds() returns true if there are more ids on the stack. | ||
} while (popAsyncIds(async_uid_fields[kCurrentAsyncId])); | ||
} while (asyncIdStackSize() > 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few questions:
- why is this better? feels less abstract/more "internal implementation exposed"
- who actually pops the ids?
- cache
emitAfter
?
const emitAfter = NativeModule.require('async_hooks').emitAfter;
do {
emitAfter(async_uid_fields[kCurrentAsyncId]);
}...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Are we sure
asyncIdStackSize() > 0
at the first iteration?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- why is this better? feels less abstract/more "internal implementation exposed"
because it fixes the bug :) and it's actually the other way around. previously I was overriding implementation details in emitAfter()
.
- who actually pops the ids?
emitAfter()
pops the id. that's why it was skipping every other id in the stack.
- cache
emitAfter
?
I'm doing it for the same reason as the require('timers')
call below. Because if the script fails early in the startup process then the module might not have been loaded yet. And require()
already caches the script into an object, doesn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
who actually pops the ids?
emitAfter() pops the id. that's why it was skipping every other id in the stack.
Ohh emitAfter
is emitAfterScript
not emitAfterNative
cache emitAfter?
I'm doing it for the same reason as the require('timers') call below. Because if the script fails early in the startup process then the module might not have been loaded yet. And require() already caches the script into an object, doesn't it?
Ack, but if you do it just before the loop it (1) looks cleaner [to me] (2) still lazy enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack, but if you do it just before the loop it (1) looks cleaner [to me] (2) still lazy enough.
do you mean creating let async_hooks = null;
in setupProcessFatal()
then doing something like?:
if (async_hooks === null)
async_hooks = NativeModule.require('async_hooks');
Or just const async_hooks = NativeModule.require('async_hooks');
before the loop every time?
assert.strictEqual(er.message, 'bye'); | ||
collect = false; | ||
})); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what happens is you throw here (where AFAICT the stack is still empty)?
What's the value of async_uid_fields[kCurrentAsyncId])
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The first pass of the script is the "bootstrap", which always has an id of 1
. But as soon as it throws the stack is cleared and async_uid_fields[kCurrentAsyncId] === 0
until another stack is entered. That answer your question?
55e8178
to
8c506d9
Compare
Another CI after rebase |
8c506d9
to
e4a04e8
Compare
New CI run: https://ci.nodejs.org/job/node-test-pull-request/9801/ (previous had a couple of unrelated failures butjust in case...) |
Running partial CI again: https://ci.nodejs.org/job/node-test-commit-arm/11727/ @trevnorris ... is this ready to go? |
Previously calling emitAfter() from _fatalException would skipt the first asyncId. Instead use the size() of the std::stack to determine how many times to loop and call emitAfter(). PR-URL: nodejs#14914 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Refael Ackermann <refack@gmail.com>
e4a04e8
to
244ada3
Compare
Previously calling emitAfter() from _fatalException would skipt the first asyncId. Instead use the size() of the std::stack to determine how many times to loop and call emitAfter(). PR-URL: nodejs/node#14914 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Refael Ackermann <refack@gmail.com>
Previously calling emitAfter() from _fatalException would skipt the first asyncId. Instead use the size() of the std::stack to determine how many times to loop and call emitAfter(). PR-URL: nodejs/node#14914 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Refael Ackermann <refack@gmail.com>
Previously calling emitAfter() from _fatalException would skipt the first asyncId. Instead use the size() of the std::stack to determine how many times to loop and call emitAfter(). PR-URL: nodejs#14914 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Refael Ackermann <refack@gmail.com>
Previously calling emitAfter() from _fatalException would skipt the first asyncId. Instead use the size() of the std::stack to determine how many times to loop and call emitAfter(). PR-URL: #14914 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Refael Ackermann <refack@gmail.com>
Previously calling emitAfter() from _fatalException would skipt the first asyncId. Instead use the size() of the std::stack to determine how many times to loop and call emitAfter(). PR-URL: #14914 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Refael Ackermann <refack@gmail.com>
Do we want to backport async_hooks as a whole before 6 goes to maintenance |
@MylesBorins We'd need to do work to remove Promise support, since the API won't exist in v6.x. @addaleax thoughts? |
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
async_hooks
Notes
Previously calling
emitAfter()
from_fatalException
would skip thefirst
asyncId
. Instead use thesize()
of thestd::stack
to determine howmany times to loop and call
emitAfter()
.CI: https://ci.nodejs.org/job/node-test-pull-request/9730/