-
Notifications
You must be signed in to change notification settings - Fork 30k
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: execute unhandledRejection cb in Promise execution context #37281
Conversation
// throw new Error('Throwing on purpose'); | ||
// }); | ||
|
||
Promise.reject(); |
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.
@benjamingr I noticed an interesting case. If you just do Promise.reject
the async_hooks.executionAsyncId()
is incorrect in process.on('unhandledRejection')
's callback. But it is correct if you do,
Promise.resolve()
.then(() => {
throw new Error('Throwing on purpose');
});
Therefore, I tried out setting the context in node_task_queue
, and then it seems to be correct.
Let me know your thoughts.
src/node_task_queue.cc
Outdated
: v8::Just(AsyncWrap::kInvalidAsyncId); | ||
} | ||
else { | ||
return Nothing<double>(); |
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 generally don't want to return a Nothing<>
unless there's an exception pending (because that's what it means)
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.
Can probably return v8::Just(AsyncWrap::kInvalidAsyncId);
here too ?
src/node_task_queue.cc
Outdated
GetAssignedPromiseWrapAsyncId(env, promise, env->async_id_symbol()) | ||
.To(&async_id); | ||
GetAssignedPromiseWrapAsyncId(env, promise, env->trigger_async_id_symbol()) | ||
.To(&trigger_async_id); |
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.
These calls can lead to JS exceptions, so I think you want to move all of this into the TryCatchScope
here and return if any of these .To()
calls return false
8699a07
to
5b5e79e
Compare
src/node_task_queue.cc
Outdated
} | ||
|
||
if (try_catch_async_id.HasCaught()) { | ||
// What must be done here? |
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 must we do here? I don't imagine this should throw. Shall we print like it's done below?
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 don’t think we’ll get to this point here, because now we’re already returning early whenever an exception happens.
You can remove this conditional (and remove the second TryCatchScope
, it’s okay to have a single one)
@addaleax @benjamingr Thank you both for the feedback. Also, I am opening this PR from draft to run CI. |
5b5e79e
to
361d583
Compare
This commit now executes `process.on('unhandledRejection')` in the async execution context of the concerned `Promise`.
361d583
to
91fd525
Compare
if (async_id == AsyncWrap::kInvalidAsyncId && | ||
trigger_async_id == AsyncWrap::kInvalidAsyncId) { | ||
// That means that promise might be a PromiseWrap, so we'll | ||
// check there as well. |
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.
Can we add tests for both cases here?
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 actually manually ran the other case by commenting this line out while running the test case added in this PR. It passed.
However, I guess we can change ActivityCollector
to not use a noop
function when ondestroy
is not provided. What do you think?
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 not sure why the test would need to use ActivityCollector
, or be in test/async-hooks
-- a lot of async_hooks tests that don't make use of the special features that that subdirectory has are just in test/parallel
.
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 see. What are these "special features" out of curiosity?
Also, if I just assumed initHooks had convenient methods when dealing with async hooks. What is otherwise the purpose?
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 are these "special features" out of curiosity?
Things like ActivityCollector
, and the rest that’s in async-hooks/init-hooks.js
and async-hooks/hook-checks.js
.
Also, if I just assumed initHooks had convenient methods when dealing with async hooks. What is otherwise the purpose?
They do, but it’s not like you have to use them. At least for the test here, the difference to using async hooks directly seems to be relatively small.
Also, are these CI failures due to flakiness? |
I guess one check still fails. Let me know if it can be ignored. Also, will wait for your guidance on this. |
Polite 🔔 |
I'm fine with this landing but I want Anna to respond regarding the test question :) If she doesn't and a week passes this can just land. |
Yeah, I'm good here, although I still think it would be good to cover both variants here. If it turns our to be hard to write a test then leaving a |
This commit now executes `process.on('unhandledRejection')` in the async execution context of the concerned `Promise`. PR-URL: #37281 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]>
Thank you, both. :) |
This commit now executes `process.on('unhandledRejection')` in the async execution context of the concerned `Promise`. PR-URL: #37281 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]>
This commit now executes
process.on('unhandledRejection')
in theasync execution context of the concerned
Promise
.Fixes #37244