Skip to content
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

process: add --unhandled-rejections flag #26599

Closed
wants to merge 2 commits into from

Conversation

BridgeAR
Copy link
Member

This adds a flag to define the default behavior for unhandled
rejections. Three modes exist: none, warn and strict. The first
is going to silence all unhandled rejection warnings. The second
behaves identical to the current default with the excetion that no
deprecation warning will be printed and the last is going to throw
an error for each unhandled rejection, just as regular exceptions do.
It is possible to intercept those with the uncaughtException hook
as with all other exceptions as well.

This PR has no influence on the existing unhandledRejection hook.
If that is used, it will continue to function as before.

Supersedes #20097

// CC @nodejs/diagnostics @nodejs/promises-debugging @nodejs/tsc

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines

@BridgeAR BridgeAR added the semver-minor PRs that contain new features and should be released in the next minor version. label Mar 11, 2019
@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. process Issues and PRs related to the process subsystem. labels Mar 11, 2019
@mmarchini
Copy link
Contributor

Code changes and proposed modes LGTM. If you don't mind, I want to investigate how this works with postmortem/llnode before we land. I'm not sure calling process.abort() is the best approach in this case and I think the stackTraceLimit reset trick to speed up Error creation might interfere with recent developments to make llnode more useful when investigating unhandled promise rejections (see https://chromium-review.googlesource.com/c/v8/v8/+/1405568 and nodejs/llnode#271).

Copy link
Member

@ljharb ljharb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although I'd still prefer the deprecation warning be removed in the default case, I'm glad it's removed when an explicit flag is passed.

lib/internal/process/promises.js Outdated Show resolved Hide resolved
src/node_options.cc Outdated Show resolved Hide resolved
Copy link
Member

@benjamingr benjamingr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

doc/api/cli.md Outdated Show resolved Hide resolved
doc/api/cli.md Outdated Show resolved Hide resolved
src/node_options.h Show resolved Hide resolved
src/node_options.cc Show resolved Hide resolved
Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@BridgeAR
Copy link
Member Author

I had to rebase due to conflicts, so PTAL.

CI https://ci.nodejs.org/job/node-test-pull-request/21457/

@mmarchini
Copy link
Contributor

From a postmortem/llnode perspective (with the flags --unhandled-rejections=strict and --abort-on-uncaught-exception set):

  1. The stack we get on the output is correct in most common cases (when we reject or throw inside a Promise/async function by passing an error to reject/throw.
  2. The ReportException called inside TriggerFatalException will turn the JSArray stack stored in the Error object into its stringified version, and the frames stored in the JSArray will be deleted. This will render src: inspcet arguments from an Error object stack llnode#271 useless, but this is how V8 works and I think we should make changes there instead of blocking this PR because of it.
  3. The stack we get on llnode (by using v8 bt) is not very useful, but this was expected and should be addressed by 2.

Copy link
Contributor

@mmarchini mmarchini left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, the only thing I think we should change is on V8 and not on Node.js, so I'll open an upstream PR for that.

Edit: Upstream PR, if anyone is interested: https://chromium-review.googlesource.com/c/v8/v8/+/1518612

Copy link
Member

@mhdawson mhdawson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM once the default behaviour is clarified.

@BridgeAR BridgeAR force-pushed the unhandled-take-xyz branch 2 times, most recently from cb8b50b to 18c420d Compare March 13, 2019 13:42
@BridgeAR
Copy link
Member Author

I improved the documentation and the warn I reworked the warn mode a tiny bit: it will now always warn (but without the deprecation notice), even if there is an unhandled rejections on in place.

The changes are in the 18c420d and a2eb1ea.

CI https://ci.nodejs.org/job/node-test-pull-request/21501/

@benjamingr
Copy link
Member

@BridgeAR so to clarify, warn doesn't show the deprecation warning and it ignores handlers (assuming they don't actually handle the rejection) and the default did not change?

@BridgeAR
Copy link
Member Author

@benjamingr

it ignores handlers

Exactly

assuming they don't actually handle the rejection

That's a good point. I forgot that they might actually add a handler. I'll add a fix for that so I verify that the promise is indeed still unhandled before printing the warning.

the default did not change

There is absolutely no behavior change if non of the flags is used. That is one of the goals with this PR.

@BridgeAR
Copy link
Member Author

Thinking about it again: I would rather always warn, even if the unhandled rejection hook attached a handler. Otherwise it would a) be possible to silence those warnings with the hook which I think is orthogonal to what the user wants if they use the warn mode and b) it increases the complexity for the implementation (I have to wait another tick and add extra information and then check if it got handled in the meanwhile).

Copy link
Member

@benjamingr benjamingr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explicit "still lgtm"

@BridgeAR
Copy link
Member Author

doc/api/cli.md Outdated Show resolved Hide resolved
doc/api/process.md Outdated Show resolved Hide resolved
@BridgeAR
Copy link
Member Author

CI https://ci.nodejs.org/job/node-test-pull-request/21570/

@mmarchini @mcollina @mhdawson @benjamingr would you be so kind and confirm your LG? To me this seems ready to land.

@BridgeAR BridgeAR added the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Mar 15, 2019
Copy link
Member

@ljharb ljharb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still seems good to me!

Perhaps could this flag be set by an environment variable? That way it would be able to affect shebangs in files, or nested node commands i might not be able to edit.

@BridgeAR BridgeAR mentioned this pull request May 7, 2019
BridgeAR added a commit to BridgeAR/node that referenced this pull request Aug 7, 2019
This adds a flag to define the default behavior for unhandled
rejections. Three modes exist: `none`, `warn` and `strict`. The first
is going to silence all unhandled rejection warnings. The second
behaves identical to the current default with the excetion that no
deprecation warning will be printed and the last is going to throw
an error for each unhandled rejection, just as regular exceptions do.
It is possible to intercept those with the `uncaughtException` hook
as with all other exceptions as well.

This PR has no influence on the existing `unhandledRejection` hook.
If that is used, it will continue to function as before.

PR-URL: nodejs#26599
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Matheus Marchini <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Reviewed-By: Сковорода Никита Андреевич <[email protected]>
Reviewed-By: Sakthipriyan Vairamani <[email protected]>
BethGriggs pushed a commit that referenced this pull request Oct 15, 2019
This adds a flag to define the default behavior for unhandled
rejections. Three modes exist: `none`, `warn` and `strict`. The first
is going to silence all unhandled rejection warnings. The second
behaves identical to the current default with the excetion that no
deprecation warning will be printed and the last is going to throw
an error for each unhandled rejection, just as regular exceptions do.
It is possible to intercept those with the `uncaughtException` hook
as with all other exceptions as well.

This PR has no influence on the existing `unhandledRejection` hook.
If that is used, it will continue to function as before.

PR-URL: #26599
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Matheus Marchini <[email protected]>
Reviewed-By: Michael Dawson <[email protected]>
Reviewed-By: Сковорода Никита Андреевич <[email protected]>
Reviewed-By: Sakthipriyan Vairamani <[email protected]>
@BethGriggs BethGriggs mentioned this pull request Oct 18, 2019
BethGriggs added a commit that referenced this pull request Oct 22, 2019
Notable changes:

* crypto:
  * add support for chacha20-poly1305 for AEAD (chux0519)
    #24081
  * increase maxmem range from 32 to 53 bits (Tobias Nießen)
    #28799
* deps:
  * update npm to 6.11.3 (claudiahdz)
    #29430
  * upgrade openssl sources to 1.1.1d (Sam Roberts)
    #29921
* dns:
  * remove dns.promises experimental warning (cjihrig)
    #26592
* fs:
  * remove experimental warning for fs.promises (Anna Henningsen)
    #26581
* http:
  * makes response.writeHead return the response (Mark S. Everitt)
    #25974
* http2:
  * makes response.writeHead return the response (Mark S. Everitt)
    #25974
* n-api:
  * make func argument of napi\_create\_threadsafe\_function optional
    (legendecas)
    #27791
  * mark version 5 N-APIs as stable (Gabriel Schulhof)
    #29401
  * implement date object (Jarrod Connolly)
    #25917
* process:
  * add --unhandled-rejections flag (Ruben Bridgewater)
    #26599
* stream:
  * implement Readable.from async iterator utility (Guy Bedford)
    #27660
  * make Symbol.asyncIterator support stable (Matteo Collina)
    #26989

PR-URL: #29875
BethGriggs added a commit that referenced this pull request Oct 22, 2019
Notable changes:

* crypto:
  * add support for chacha20-poly1305 for AEAD (chux0519)
    #24081
  * increase maxmem range from 32 to 53 bits (Tobias Nießen)
    #28799
* deps:
  * update npm to 6.11.3 (claudiahdz)
    #29430
  * upgrade openssl sources to 1.1.1d (Sam Roberts)
    #29921
* dns:
  * remove dns.promises experimental warning (cjihrig)
    #26592
* fs:
  * remove experimental warning for fs.promises (Anna Henningsen)
    #26581
* http:
  * makes response.writeHead return the response (Mark S. Everitt)
    #25974
* http2:
  * makes response.writeHead return the response (Mark S. Everitt)
    #25974
* n-api:
  * make func argument of napi\_create\_threadsafe\_function optional
    (legendecas)
    #27791
  * mark version 5 N-APIs as stable (Gabriel Schulhof)
    #29401
  * implement date object (Jarrod Connolly)
    #25917
* process:
  * add --unhandled-rejections flag (Ruben Bridgewater)
    #26599
* stream:
  * implement Readable.from async iterator utility (Guy Bedford)
    #27660
  * make Symbol.asyncIterator support stable (Matteo Collina)
    #26989

PR-URL: #29875
@BridgeAR BridgeAR deleted the unhandled-take-xyz branch January 20, 2020 12:02
dfabulich added a commit to dfabulich/node that referenced this pull request Apr 23, 2020
--unhandled-rejections has three explicit modes (strict, warn, none)
plus one implicit "default" mode, which logs an additional deprecation
warning (DEP0018).

Prior to this commit, the default mode was subtly different from warn
mode. If the unhandledRejections hook is set, default mode suppresses
all warnings. In warn mode, unhandledRejections would always fire a
warning, regardless of whether the hook was set.

In addition, prior to this commit, strict mode would always throw an
exception, regardless of whether the hook was set.

In this commit, all modes honor the unhandledRejections hook. If the
user has set the hook, then the user has taken full responsibility over
the behavior of unhandled rejections. In that case, no additional
warnings or thrown exceptions will be fired, even in warn mode or
strict mode.

This commit is a stepping stone towards resolving DEP0018. After this
commit, any code that includes an unhandledRejection hook will behave
unchanged when we change the default mode.

Refs: nodejs#26599
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
author ready PRs that have at least one approval, no pending requests for changes, and a CI started. c++ Issues and PRs that require attention from people who are familiar with C++. process Issues and PRs related to the process subsystem. semver-minor PRs that contain new features and should be released in the next minor version.
Projects
None yet
Development

Successfully merging this pull request may close these issues.