-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
unhandledRejection falls into infinite recursion #17913
Comments
I propose to emit warning about promise unhandled rejection on the second recursion call, and exit process with error code, probably some special code to indicate specificity of this exit event. I don't expect that any code rely on this behavior, so I assume that it's safe to fix it. |
Working as intended, IMO. If you replace it with a |
Okay, let me show you some another code.
you got the idea ? |
Why we cannot say the same thing about uncaughtException. "There is no recursion, just repeated uncaughtException events." ? But uncaughtException IMO has correct behavior avoiding infinite recursion. The same should have unhandledRejection. |
@eduardbcom Since |
By saying infinite recursion I mean that we infinitely entering that function. And there is a case when no another code would be run cuz user's micro function can completely fill up promise micro stack. |
As a plus sign, I don't see any advantage in current implementation. Any reason to love this behavior ? @apapirovski that was not working code :) |
@eduardbcom After looking at the code, I don't think the current behaviour is intended. Pretty sure it was meant to let the event loop proceed first. |
@apapirovski but you also don't like the idea about process.exit on the second sequential call ? don't get me wrong, its okay to emit |
@eduardbcom I think that we should conform to the expected async behaviour of promises. The problem is that the current code that emits @bnoordhuis I think we need to at least allow the node/lib/internal/process/promises.js Lines 100 to 116 in 4117e22
As you can see, the |
Can fix it, but we need to reach an agreement of the expected behavior. |
Something like this is acceptable, IMO: const rejections = pendingUnhandledRejections;
pendingUnhandledRejections = [];
while (rejections.length > 0) {
// ...
} (And might as well change to that a for (let i = 0; i < rejections.length; i += 2) {
const promise = rejections[i + 0];
const reason = rejections[i + 1];
// ...
} Anything more complex is probably not worth it because it's an edge case and the plan is to make unhandled rejections fatal errors anyway. |
Even in the case we listen that event ? |
I think the expected behavior is for them to be fatal. However, it is very hard to reach an agreement on the matter. I have a polyfill for that behavior if you want to try that out: https://github.com/mcollina/make-promises-safe. I think this is too much of an edge case and a programmer error: I do not think it's Node.js responsibility to handle. |
Remove the unnecessary microTasksTickObject for scheduling microtasks and instead use TickInfo to keep track of whether promise rejections exist that need to be emitted. Consequently allow the microtasks to execute on average fewer times, in more predictable manner than previously. Simplify unhandled & handled rejection tracking to do more in C++ to avoid needing to expose additional info in JS. When new unhandledRejections are emitted within an unhandledRejection handler, allow the event loop to proceed first instead. This means that if the end-user code handles all promise rejections on nextTick, rejections within unhandledRejection now won't spiral into an infinite loop. PR-URL: nodejs#18207 Fixes: nodejs#17913 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Remove the unnecessary microTasksTickObject for scheduling microtasks and instead use TickInfo to keep track of whether promise rejections exist that need to be emitted. Consequently allow the microtasks to execute on average fewer times, in more predictable manner than previously. Simplify unhandled & handled rejection tracking to do more in C++ to avoid needing to expose additional info in JS. When new unhandledRejections are emitted within an unhandledRejection handler, allow the event loop to proceed first instead. This means that if the end-user code handles all promise rejections on nextTick, rejections within unhandledRejection now won't spiral into an infinite loop. PR-URL: nodejs#18207 Fixes: nodejs#17913 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
unhandledRejection
event)According to documentation of
uncaughtException
- 'Exceptions thrown from within the event handler will not be caught. Instead the process will exit with a non-zero exit code and the stack trace will be printed. This is to avoid infinite recursion.'.So why
unhandledRejection
allows you to fall into infinite recursion if code within handler creates unhandled promise rejection ? I expect the same behavior as foruncaughtException
(exit process with non-zero code).unhandledRejection
handler may contain some logic to log that situation, and owing to the fact that 3-d party logger implementation can produce unhandled rejection within himself , we can have infinite recursion.Code example to reproduce:
Thanks in advance.
The text was updated successfully, but these errors were encountered: