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

async_hooks: skip sanity checks when disabled #15454

Closed
wants to merge 1 commit into from
Closed

async_hooks: skip sanity checks when disabled #15454

wants to merge 1 commit into from

Conversation

AndreasMadsen
Copy link
Member

@AndreasMadsen AndreasMadsen commented Sep 18, 2017

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines
Affected core subsystem(s)

async_hooks

While async_hooks is experimental we should skip the sanity checks when async_hooks is disabled. If someone would like a flag as well, we could add another async_hooks_field that is > 0 when either the flag is used or the hooks are enabled. Should be trivial.

This makes the sanity checks stricter when async_hooks is enabled, so be sure to run CITGM before merging this. However, since async_hooks is rarely enabled there shouldn't be any issues.

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

Ref: #14387
Ref: #14722
Ref: #14717
Ref: #15448

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory. labels Sep 18, 2017
@AndreasMadsen AndreasMadsen added the async_hooks Issues and PRs related to the async hooks subsystem. label Sep 18, 2017
@AndreasMadsen
Copy link
Member Author

AndreasMadsen commented Sep 18, 2017

/cc @nodejs/async_hooks @mcollina

@refack
Copy link
Contributor

refack commented Sep 18, 2017

👍
IMO adding a state flag (CLI or ENV) to enable state validation even if there are no hooks, would make this even better. (similar in concept to --abort-on-uncaught-exception or --abort-on-unhandled-rejection)

  1. For debugging, and CI time assertions (even though we have
    // If env var is set then enable async_hook hooks for all tests.
    if (process.env.NODE_TEST_WITH_ASYNC_HOOKS) {
    ). Making sure the assertion are active irrespective of transient state seems cleanest.
  2. For use-cases where the state is important for full processes lifespan, but temporarily hooks might not be registered.

As for the current implementation, I'd like to see it more encapsulated, maybe like:
js

const { validateAsyncId, validateTriggerId } = process.binding('async_wrap')
...
const id = validateAsyncId(argId);

cpp

Environment::AsyncHooks::validate_ids(double async_id, double trigger_id);

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.

I'm definitely 👍 on this approach. Before landing we should verify that we do not break shot and hapi tests, even with async_hooks enabled: http://npm.im/shot.

There is a plan to move domains on top of async-hooks and the hapi community use domains.

@AndreasMadsen
Copy link
Member Author

AndreasMadsen commented Sep 18, 2017

@refack I've created a validation function on the JS side. On the C++ side, I would prefer to keep it as it. There aren't that many validations and only the line where the macro is used is shown in the error. If I merge those asserts it will be more difficult to know which assert failed.

I will look into adding the flag.

@AndreasMadsen
Copy link
Member Author

@refack I've added a --async-hooks-sanity-check flag, please check :)

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

doc/api/cli.md Outdated
-->

Enables sanity checks for async_hooks. These can also be enabled in runtime
by enabling one of the `async_hooks` hooks.
Copy link
Member

Choose a reason for hiding this comment

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

Is the intent to leave this flag in forever?
Also, would prefer to take -sanity out... just --async-hooks-check

Copy link
Member Author

Choose a reason for hiding this comment

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

Is the intent to leave this flag in forever?

Hopefully, we can become so robust the checks are always enabled.

Also, would prefer to take -sanity out... just --async-hooks-check

That is fine :)

if (triggerAsyncId !== null)
validateAsyncId(triggerAsyncId, 'triggerAsyncId');
if (async_hook_fields[kSanityCheck] > 0 &&
(typeof type !== 'string' || type.length <= 0)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Indentation is missing a single space here?

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't know. The linter says it is fine.

Copy link
Contributor

Choose a reason for hiding this comment

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

hm. another one of those things we do so regularly I didn't realize we needed a linter fix for. If you run this you'll see that >90% of these would have one more space

git grep -A 1 " if (.*[^{);]$" lib/

i'll check on getting a rule into the linter.

@AndreasMadsen
Copy link
Member Author

@addaleax
Copy link
Member

I probably should have come up with this sooner, but how about just printing warnings in these cases instead of crashing, and that unconditionally? That should help find bugs while at the same time preventing crashes …

@AndreasMadsen
Copy link
Member Author

I probably should have come up with this sooner, but how about just printing warnings in these cases instead of crashing, and that unconditionally? That should help find bugs while at the same time preventing crashes …

My understand from @trevnorris was that it would leave async_hooks in too strange a state to be useful. Perhaps I misunderstood, a warning is reasonable to me.

@refack
Copy link
Contributor

refack commented Sep 18, 2017

I like it. Maybe the names need some bikeshedding, but I have no strong opinions.

@refack
Copy link
Contributor

refack commented Sep 18, 2017

Maybe one more thing, add the CLI flag to NODE_OPTIONS:

node/src/node.cc

Lines 3936 to 3943 in 1a0727d

static void CheckIfAllowedInEnv(const char* exe, bool is_env,
const char* arg) {
if (!is_env)
return;
static const char* whitelist[] = {
// Node options, sorted in `node --help` order for ease of comparison.
"--require", "-r",

(had an idea for CLI flag name --abort-on-async-hooks-check not good, implies that without flag might not abort)

@AndreasMadsen
Copy link
Member Author

Maybe one more thing, add the CLI flag to NODE_OPTIONS.

Sorry, I don't understand what you mean. Could you be very explicit :)

@AndreasMadsen
Copy link
Member Author

I like it. Maybe the names need some bikeshedding, but I have no strong opinions.

Bring it, I'm not so happy about the names either :)

@refack
Copy link
Contributor

refack commented Sep 19, 2017

Maybe one more thing, add the CLI flag to NODE_OPTIONS.

Sorry, I don't understand what you mean. Could you be very explicit :)

NODE_OPTIONS is an environment variable that is used to pass multiple CLI arguments to the node binary - https://nodejs.org/api/cli.html#cli_node_options_options
It only allows CLI args from a whitelist -

node/src/node.cc

Lines 3941 to 3946 in 1a0727d

static const char* whitelist[] = {
// Node options, sorted in `node --help` order for ease of comparison.
"--require", "-r",
"--inspect",
"--inspect-brk",
"--inspect-port",

In order for the new arg to be able to be used via NODE_OPTIONS it needs to be added to the whitelist, and probably to the test test/parallel/test-cli-node-options.js (or to the negative test test/parallel/test-cli-node-options-disallowed.js` if we decide to blacklist it).

As for the arg name IMHO it's missing a verb. I think force is a good one, to give us - --force-async-hooks-checks

@jasnell
Copy link
Member

jasnell commented Sep 19, 2017

Bring it, I'm not so happy about the names either :)

I think just avoiding the word "sanity" throughout would be better... everything else looks fine to me.

src/node.cc Outdated
@@ -3953,6 +3959,7 @@ static void CheckIfAllowedInEnv(const char* exe, bool is_env,
"--trace-warnings",
"--redirect-warnings",
"--trace-sync-io",
"--async-hooks-check",
Copy link
Member Author

Choose a reason for hiding this comment

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

@refack is this the line you are talking about?

let socketAsyncId = this.socket[async_id_symbol];
// If the socket was set directly it won't be correctly initialized
// with an async_id_symbol.
// TODO(AndreasMadsen): @trevnorris sugested some more correct solution
Copy link
Contributor

Choose a reason for hiding this comment

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

typo: "suggested"

src/env-inl.h Outdated
if (fields_[kSanityCheck] > 0) {
CHECK_GE(async_id, 0);
CHECK_GE(trigger_id, 0);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

hm. this is cool for release builds, but i think they should also always be on in debug builds.

Copy link
Member Author

Choose a reason for hiding this comment

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

They are always on in tests, and you can `alias node='node --force-async-hooks-check' if you like. I think it is important that we have them opt-in in release builds too.

Copy link
Contributor

Choose a reason for hiding this comment

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

And export NODE_OPTIONS=--force-async-hooks-check.

@trevnorris
Copy link
Contributor

I understand where this comes from but allowing the stack to possibly get corrupted makes my stomach turn. It also inhibits the usefulness of async_hooks.executionAsyncId()/async_hooks.triggerAsyncId(), and since other core utilities are becoming dependent on async hooks we should take into consideration how allowing bad values through would affect them. I understand that being "experimental" means certain things, but even so I wonder if disabling all checks will help. i.e. bugs will get through that'll surface once the checks are always enabled, once it's no longer experimental.

I do like that you've yanked out the value checks into a single function.

@AndreasMadsen
Copy link
Member Author

AndreasMadsen commented Sep 21, 2017

@trevnorris we have been playing this game for a long time. I don't think we can go into LTS with node being this unstable. To my mind, it has little to do with async_hooks being experimental, but rather it is because we keep seeing errors. I think we have reached the point where we need to try a different solution. Also, this PR actually makes some of the checks more strict, but only when async_hooks is enabled or the flag is passed, thus it also helps us to find errors.

Regarding async_hooks.executionAsyncId() and async_hooks.triggerAsyncId() they are already corrupted when promises are used and async_hooks isn't enabled. This is because of how we lazy initialize in the PromiseHooks. If you like we could print a warning suggesting to use the --force-async-hooks-checks.

@@ -7,23 +7,12 @@ const spawn = require('child_process').spawn;

const script = `
const assert = require('assert');
const async_wrap = process.binding('async_wrap');
const {kTotals} = async_wrap.constants;
Copy link
Member

Choose a reason for hiding this comment

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

I think if this were a “real” script out linter would expect spaces inside {} … no big deal, tho :)

@refack
Copy link
Contributor

refack commented Sep 21, 2017

TN: I understand that being "experimental" means certain things, but even so I wonder if disabling all checks will help.

AM: I don't think we can go into LTS with node being this unstable.

So the tl;dr is can we converge on all the errors before LTS (~40 days)? If not then IMHO we need this PR 🤷‍♂️
Otherwise we are entering LTS with (1) an experimental module that's effectively always on (2) adding instability through assertion of invariants that may not be used.

Maybe turn this back to always-on for v9.x, but keeping it opt-in for v8.x LTS?

@refack
Copy link
Contributor

refack commented Sep 21, 2017

P.S. Ironically those that do use async-hooks are happy (from what I'm hearing via: #14794, anecdotes from new-relic, and I assume Iron Source)

@AndreasMadsen
Copy link
Member Author

@AndreasMadsen
Copy link
Member Author

AndreasMadsen commented Oct 19, 2017

Two test failures. Both appear to be unrelated.

Raspbian

fs.js:924
  return binding.readdir(pathModule.toNamespacedPath(path), options.encoding);
                 ^

Error: ENOENT: no such file or directory, scandir '/home/iojs/build/workspace/node-test-binary-arm/out/doc/api'
    at Object.fs.readdirSync (fs.js:924:18)
    at Object.<anonymous> (/home/iojs/build/workspace/node-test-binary-arm/test/sequential/test-make-doc.js:15:17)
    at Module._compile (module.js:607:30)
    at Object.Module._extensions..js (module.js:618:10)
    at Module.load (module.js:526:32)
    at tryModuleLoad (module.js:489:12)
    at Function.Module._load (module.js:481:3)
    at Function.Module.runMain (module.js:648:10)
    at startup (bootstrap_node.js:191:16)
    at bootstrap_node.js:609:3

AIX

/home/iojs/build/workspace/node-test-commit-aix/nodes/aix61-ppc64/test/sequential/test-fs-readfile-tostring-fail.js:57
  throw err;
  ^

AssertionError [ERR_ASSERTION]: false == true
    at /home/iojs/build/workspace/node-test-commit-aix/nodes/aix61-ppc64/test/sequential/test-fs-readfile-tostring-fail.js:31:12
    at /home/iojs/build/workspace/node-test-commit-aix/nodes/aix61-ppc64/test/common/index.js:531:15
    at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:528:3)

rerunning AIX: https://ci.nodejs.org/job/node-test-commit-aix/nodes=aix61-ppc64/9499/

@richardlau
Copy link
Member

The AIX failure is being addressed by #16273.

@AndreasMadsen
Copy link
Member Author

@richardlau thanks. Found the other too: #16301

We can land :)

@AndreasMadsen
Copy link
Member Author

Landed in 7c079d1

@mcollina mcollina added dont-land-on-v4.x and removed tsc-agenda Issues and PRs to discuss during the meetings of the TSC. labels Oct 19, 2017
@AndreasMadsen
Copy link
Member Author

AndreasMadsen commented Oct 19, 2017

I will prepear the dont-land-on-v8.x PR :)

MylesBorins pushed a commit that referenced this pull request Oct 23, 2017
PR-URL: #15454
Ref: #14387
Ref: #14722
Ref: #14717
Ref: #15448
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
addaleax pushed a commit to ayojs/ayo that referenced this pull request Oct 26, 2017
PR-URL: nodejs/node#15454
Ref: nodejs/node#14387
Ref: nodejs/node#14722
Ref: nodejs/node#14717
Ref: nodejs/node#15448
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
jasnell pushed a commit that referenced this pull request Oct 30, 2017
Ref: #15454
PR-URL: #16318
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Qard pushed a commit to ayojs/ayo that referenced this pull request Nov 2, 2017
Ref: nodejs/node#15454
PR-URL: nodejs/node#16318
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Qard pushed a commit to ayojs/ayo that referenced this pull request Nov 2, 2017
Ref: nodejs/node#15454
PR-URL: nodejs/node#16318
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Refael Ackermann <refack@gmail.com>
addaleax pushed a commit to ayojs/ayo that referenced this pull request Dec 7, 2017
PR-URL: nodejs/node#15454
Ref: nodejs/node#14387
Ref: nodejs/node#14722
Ref: nodejs/node#14717
Ref: nodejs/node#15448
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
addaleax pushed a commit to ayojs/ayo that referenced this pull request Dec 7, 2017
Ref: nodejs/node#15454
PR-URL: nodejs/node#16318
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Refael Ackermann <refack@gmail.com>
daeyeon added a commit to daeyeon/node that referenced this pull request Jun 5, 2022
This removes a comment relevant to runtime checks for `async_hooks`.

Even if `async_hooks` is experimental, the check pointed by the comment
is performed as default unless either `--no-force-async-hooks-checks`
is given from CLI arguments or any async_hook is enabled.

Refs: nodejs#16318
Refs: nodejs#15454 (comment)

Signed-off-by: Daeyeon Jeong daeyeon.dev@gmail.com
daeyeon added a commit to daeyeon/node that referenced this pull request Jun 5, 2022
This removes a comment relevant to runtime checks for `async_hooks`.

Even if `async_hooks` is experimental, the check pointed by the comment
is performed as default unless `--no-force-async-hooks-checks` is given
from CLI arguments.

Refs: nodejs#16318
Refs: nodejs#15454 (comment)

Signed-off-by: Daeyeon Jeong daeyeon.dev@gmail.com
daeyeon added a commit to daeyeon/node that referenced this pull request Jun 5, 2022
This removes a comment relevant to runtime checks for `async_hooks`.

Even if `async_hooks` is experimental, the check pointed by the comment
is performed as default unless `--no-force-async-hooks-checks` is given
from CLI arguments.

Refs: nodejs#16318
Refs: nodejs#15454 (comment)

Signed-off-by: Daeyeon Jeong daeyeon.dev@gmail.com
daeyeon added a commit to daeyeon/node that referenced this pull request Jun 5, 2022
This removes a comment relevant to runtime checks for `async_hooks`.

Even if `async_hooks` is experimental, the check pointed by the comment
is performed as default unless `--no-force-async-hooks-checks` is given
from CLI arguments.

Refs: nodejs#16318
Refs: nodejs#15454 (comment)

Signed-off-by: Daeyeon Jeong daeyeon.dev@gmail.com
daeyeon added a commit to daeyeon/node that referenced this pull request Jun 19, 2022
This removes a comment relevant to runtime checks for `async_hooks`.

Even if `async_hooks` is experimental, the check pointed by the comment
is performed as default unless `--no-force-async-hooks-checks` is given
from CLI arguments.

Refs: nodejs#16318
Refs: nodejs#15454 (comment)

Signed-off-by: Daeyeon Jeong daeyeon.dev@gmail.com
aduh95 pushed a commit that referenced this pull request Jun 30, 2022
This removes a comment relevant to runtime checks for `async_hooks`.

Even if `async_hooks` is experimental, the check pointed by the comment
is performed as default unless `--no-force-async-hooks-checks` is given
from CLI arguments.

Refs: #16318
Refs: #15454 (comment)

Signed-off-by: Daeyeon Jeong daeyeon.dev@gmail.com

PR-URL: #43317
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com>
targos pushed a commit that referenced this pull request Jul 12, 2022
This removes a comment relevant to runtime checks for `async_hooks`.

Even if `async_hooks` is experimental, the check pointed by the comment
is performed as default unless `--no-force-async-hooks-checks` is given
from CLI arguments.

Refs: #16318
Refs: #15454 (comment)

Signed-off-by: Daeyeon Jeong daeyeon.dev@gmail.com

PR-URL: #43317
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com>
targos pushed a commit that referenced this pull request Jul 20, 2022
This removes a comment relevant to runtime checks for `async_hooks`.

Even if `async_hooks` is experimental, the check pointed by the comment
is performed as default unless `--no-force-async-hooks-checks` is given
from CLI arguments.

Refs: #16318
Refs: #15454 (comment)

Signed-off-by: Daeyeon Jeong daeyeon.dev@gmail.com

PR-URL: #43317
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com>
targos pushed a commit that referenced this pull request Jul 31, 2022
This removes a comment relevant to runtime checks for `async_hooks`.

Even if `async_hooks` is experimental, the check pointed by the comment
is performed as default unless `--no-force-async-hooks-checks` is given
from CLI arguments.

Refs: #16318
Refs: #15454 (comment)

Signed-off-by: Daeyeon Jeong daeyeon.dev@gmail.com

PR-URL: #43317
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com>
guangwong pushed a commit to noslate-project/node that referenced this pull request Oct 10, 2022
This removes a comment relevant to runtime checks for `async_hooks`.

Even if `async_hooks` is experimental, the check pointed by the comment
is performed as default unless `--no-force-async-hooks-checks` is given
from CLI arguments.

Refs: nodejs/node#16318
Refs: nodejs/node#15454 (comment)

Signed-off-by: Daeyeon Jeong daeyeon.dev@gmail.com

PR-URL: nodejs/node#43317
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
async_hooks Issues and PRs related to the async hooks subsystem. c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory.
Projects
None yet
Development

Successfully merging this pull request may close these issues.