-
-
Notifications
You must be signed in to change notification settings - Fork 33.6k
async_hooks: fix nested hooks mutation #14143
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: fix nested hooks mutation #14143
Conversation
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.
You kept crypto here, was that intentional? If so, it probably needs a guard for skipping the test if appropriate
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.
That is from the blocking PR, I will rebase once that is fixed.
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.
-0.1
lib/async_hooks.js
Outdated
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.
I'm worried that doing reference counting is too fragile.
Why not replace the for either with a .forEach for with a for (const hook of Array.from(active_hooks_array))
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.
I'm worried that doing reference counting is too fragile.
Could you be more explicit?
edit: Just to avoid confusion, this is not a reference counting it is a depth counting.
Why not replace the for either with a
.forEach
.forEach is not resistant to mutation.
const a = [1,2,3];
a.forEach(function (value) {
process._rawDebug(value);
a.pop();
});prints 1 2.
with a
for (const hook of Array.from(active_hooks_array))
Array copy is too slow. When async_hooks is enabled this is the hottest code path we have.
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. I was sure .forEach iterated over a fixed array (it just ignores newly added elements)
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.
Just a 2 nits
lib/async_hooks.js
Outdated
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.
nit: Since we are going with depth counting, IMHO the decrement should be in a finally clause
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.
I guess, but there is no way to escape fatalError so the code will never be executed.
The try catch finally order is:
try {
throw new Error();
} catch (e) {
console.log('catch');
} finally {
console.log('finally');
}outputs catch finally.
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.
I guess, but there is no way to escape fatalError so the code will never be executed.
At the moment... If at some point we'll enable a fatalError trap this will break. Better to be explicit about these.
Reference/depth counting only works if it's ACID
lib/async_hooks.js
Outdated
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.
finally
This fixes an error that could occure by nesting async_hooks calls
In some cases restoreTmpHooks is called too early, this causes active_hooks_array to change during execution of the init hooks.
for when node is compiled without crypto support
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.
Thanks much. Especially for the additional code comment in init(). Have a non-blocking nit to change the processing_hooks code comment to explain that it's a depth counter.
| // sure active_hooks_array isn't altered in mid execution if another hook is | ||
| // added or removed. | ||
| var processing_hook = false; | ||
| var processing_hook = 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.
Possibly change comment above from simply
Track whether a hook [...]
to something like
Use a counter to track [...] and prevent nested calls [...]
|
Fixed the nit. I had to use some artistic freedom to fit in the "prevent nested calls" part. But the meaning should be the same. |
|
landed in f94fd0c |
|
@AndreasMadsen Awesome. Thanks for adding the comment changes. |
In some cases restoreTmpHooks is called too early, this causes active_hooks_array to change during execution of the init hooks. PR-URL: #14143 Ref: #14054 (comment) Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Trevor Norris <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
In some cases restoreTmpHooks is called too early, this causes active_hooks_array to change during execution of the init hooks. PR-URL: #14143 Ref: #14054 (comment) Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Trevor Norris <[email protected]> Reviewed-By: Anna Henningsen <[email protected]>
Checklist
make -j4 test(UNIX), orvcbuild test(Windows) passesAffected core subsystem(s)
async_hooks
In some cases
restoreTmpHooksis called too early, this causesactive_hooks_arrayto change during execution of the init hooks.This depends on #14054