async_hooks: execute unhandledRejection cb in Promise execution context#37281
async_hooks: execute unhandledRejection cb in Promise execution context#37281sajal50 wants to merge 1 commit intonodejs:masterfrom
Conversation
| // throw new Error('Throwing on purpose'); | ||
| // }); | ||
|
|
||
| Promise.reject(); |
There was a problem hiding this comment.
@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.
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.
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.
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.
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.
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.
Can we add tests for both cases here?
There was a problem hiding this comment.
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.
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.
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.
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 <anna@addaleax.net>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
|
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 <anna@addaleax.net>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
This commit now executes
process.on('unhandledRejection')in theasync execution context of the concerned
Promise.Fixes #37244