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,worker: fix process.exit() crashes in async fn with async_hook enabled #33347

Closed

Conversation

addaleax
Copy link
Member

worker: call CancelTerminateExecution() before exiting Locker

As the comment indicates, this fixes a DCHECK failure, although I don’t
quite understand why it is happening in the first place.

async_hooks: clear async_id_stack for terminations in more places

Termination exceptions are similar to uncaught exceptions in that they
should clear the async id stack, because no ongoing async callbacks
will be brought to completion when execution terminates.

Previously, there was a check that made sure that that happened when
the termination occurred during the callback itself, but no such check
was in place for the case that the termination occurred during
microtasks started by them. This commit adds such a check, both for
microtasks and the nextTick queue. The latter addition doesn’t fix
a crash, but still makes sense conceptually.

The condition here is also flipped from applying only on Worker threads
to also applying on the main thread, and setting the failed_ flag
rather than reading it. The former makes sense because the public C++
Stop(env) API can have the same effect as worker thread termination,
but on the main thread rather than a Worker thread.

test: regression tests for async_hooks + Promise + Worker interaction

Add regression tests for the case in which an async_hook is enabled
inside a Worker thread and process.exit() is called during the
async part of an async function.

This commit includes multiple tests that seem like they should all
crash in a similar way, but interestingly don’t. In particular, it’s
surprising that the presence of a statement after process.exit()
in a function has an effect on the kind of crash that’s being
exhibited (V8 DCHECK vs. assertion in our own code) and the
circumstances under which it crashes (e.g. the -1 and -2 tests
can be “fixed” by reverting 13c5a16, although they
should have the same behavior as the -3 and -4 tests).

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

As the comment indicates, this fixes a DCHECK failure, although I don’t
quite understand why it is happening in the first place.
Termination exceptions are similar to uncaught exceptions in that they
should clear the async id stack, because no ongoing async callbacks
will be brought to completion when execution terminates.

Previously, there was a check that made sure that that happened when
the termination occurred during the callback itself, but no such check
was in place for the case that the termination occurred during
microtasks started by them. This commit adds such a check, both for
microtasks and the `nextTick` queue. The latter addition doesn’t fix
a crash, but still makes sense conceptually.

The condition here is also flipped from applying only on Worker threads
to also applying on the main thread, and setting the `failed_` flag
rather than reading it. The former makes sense because the public C++
`Stop(env)` API can have the same effect as worker thread termination,
but on the main thread rather than a Worker thread.
Add regression tests for the case in which an async_hook is enabled
inside a Worker thread and `process.exit()` is called during the
async part of an async function.

This commit includes multiple tests that seem like they should all
crash in a similar way, but interestingly don’t. In particular, it’s
surprising that the presence of a statement after `process.exit()`
in a function has an effect on the kind of crash that’s being
exhibited (V8 DCHECK vs. assertion in our own code) and the
circumstances under which it crashes (e.g. the -1 and -2 tests
can be “fixed” by reverting 13c5a16, although they
should have the same behavior as the -3 and -4 tests).
@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. worker Issues and PRs related to Worker support. labels May 11, 2020
@addaleax addaleax added the async_hooks Issues and PRs related to the async hooks subsystem. label May 11, 2020
@nodejs-github-bot
Copy link
Collaborator

nodejs-github-bot commented May 11, 2020

CI: https://ci.nodejs.org/job/node-test-pull-request/31271/ (:yellow_heart:)

@benjamingr
Copy link
Member

This is surprising, reading 13c5a16 I don't understand why it causes the test behavior change.

(The changes themselves in this PR look fine although I also don't understand why CancelTerminateExecution is needed)

…raction

Co-authored-by: Colin Ihrig <cjihrig@gmail.com>
@addaleax
Copy link
Member Author

This is surprising, reading 13c5a16 I don't understand why it causes the test behavior change.

Me neither, really.

(The changes themselves in this PR look fine although I also don't understand why CancelTerminateExecution is needed)

Yeah, me neither. I think the reason that V8 aborts here is that some TryCatch catches the termination exception and doesn’t properly clean up after itself, but that seems weird too.

@addaleax addaleax added the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label May 11, 2020
@nodejs-github-bot
Copy link
Collaborator

nodejs-github-bot commented May 11, 2020

addaleax added a commit that referenced this pull request May 15, 2020
As the comment indicates, this fixes a DCHECK failure, although I don’t
quite understand why it is happening in the first place.

PR-URL: #33347
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
addaleax added a commit that referenced this pull request May 15, 2020
Termination exceptions are similar to uncaught exceptions in that they
should clear the async id stack, because no ongoing async callbacks
will be brought to completion when execution terminates.

Previously, there was a check that made sure that that happened when
the termination occurred during the callback itself, but no such check
was in place for the case that the termination occurred during
microtasks started by them. This commit adds such a check, both for
microtasks and the `nextTick` queue. The latter addition doesn’t fix
a crash, but still makes sense conceptually.

The condition here is also flipped from applying only on Worker threads
to also applying on the main thread, and setting the `failed_` flag
rather than reading it. The former makes sense because the public C++
`Stop(env)` API can have the same effect as worker thread termination,
but on the main thread rather than a Worker thread.

PR-URL: #33347
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
addaleax added a commit that referenced this pull request May 15, 2020
Add regression tests for the case in which an async_hook is enabled
inside a Worker thread and `process.exit()` is called during the
async part of an async function.

This commit includes multiple tests that seem like they should all
crash in a similar way, but interestingly don’t. In particular, it’s
surprising that the presence of a statement after `process.exit()`
in a function has an effect on the kind of crash that’s being
exhibited (V8 DCHECK vs. assertion in our own code) and the
circumstances under which it crashes (e.g. the -1 and -2 tests
can be “fixed” by reverting 13c5a16, although they
should have the same behavior as the -3 and -4 tests).

PR-URL: #33347
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
@addaleax
Copy link
Member Author

Landed in c7eeef5...e65d189

@addaleax addaleax closed this May 15, 2020
@addaleax addaleax deleted the async-hooks-promises-terminate branch May 15, 2020 17:38
codebytere pushed a commit that referenced this pull request May 16, 2020
As the comment indicates, this fixes a DCHECK failure, although I don’t
quite understand why it is happening in the first place.

PR-URL: #33347
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
codebytere pushed a commit that referenced this pull request May 16, 2020
Termination exceptions are similar to uncaught exceptions in that they
should clear the async id stack, because no ongoing async callbacks
will be brought to completion when execution terminates.

Previously, there was a check that made sure that that happened when
the termination occurred during the callback itself, but no such check
was in place for the case that the termination occurred during
microtasks started by them. This commit adds such a check, both for
microtasks and the `nextTick` queue. The latter addition doesn’t fix
a crash, but still makes sense conceptually.

The condition here is also flipped from applying only on Worker threads
to also applying on the main thread, and setting the `failed_` flag
rather than reading it. The former makes sense because the public C++
`Stop(env)` API can have the same effect as worker thread termination,
but on the main thread rather than a Worker thread.

PR-URL: #33347
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
codebytere pushed a commit that referenced this pull request May 16, 2020
Add regression tests for the case in which an async_hook is enabled
inside a Worker thread and `process.exit()` is called during the
async part of an async function.

This commit includes multiple tests that seem like they should all
crash in a similar way, but interestingly don’t. In particular, it’s
surprising that the presence of a statement after `process.exit()`
in a function has an effect on the kind of crash that’s being
exhibited (V8 DCHECK vs. assertion in our own code) and the
circumstances under which it crashes (e.g. the -1 and -2 tests
can be “fixed” by reverting 13c5a16, although they
should have the same behavior as the -3 and -4 tests).

PR-URL: #33347
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
@codebytere codebytere mentioned this pull request May 18, 2020
codebytere pushed a commit that referenced this pull request Jun 7, 2020
As the comment indicates, this fixes a DCHECK failure, although I don’t
quite understand why it is happening in the first place.

PR-URL: #33347
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
codebytere pushed a commit that referenced this pull request Jun 7, 2020
Termination exceptions are similar to uncaught exceptions in that they
should clear the async id stack, because no ongoing async callbacks
will be brought to completion when execution terminates.

Previously, there was a check that made sure that that happened when
the termination occurred during the callback itself, but no such check
was in place for the case that the termination occurred during
microtasks started by them. This commit adds such a check, both for
microtasks and the `nextTick` queue. The latter addition doesn’t fix
a crash, but still makes sense conceptually.

The condition here is also flipped from applying only on Worker threads
to also applying on the main thread, and setting the `failed_` flag
rather than reading it. The former makes sense because the public C++
`Stop(env)` API can have the same effect as worker thread termination,
but on the main thread rather than a Worker thread.

PR-URL: #33347
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
codebytere pushed a commit that referenced this pull request Jun 7, 2020
Add regression tests for the case in which an async_hook is enabled
inside a Worker thread and `process.exit()` is called during the
async part of an async function.

This commit includes multiple tests that seem like they should all
crash in a similar way, but interestingly don’t. In particular, it’s
surprising that the presence of a statement after `process.exit()`
in a function has an effect on the kind of crash that’s being
exhibited (V8 DCHECK vs. assertion in our own code) and the
circumstances under which it crashes (e.g. the -1 and -2 tests
can be “fixed” by reverting 13c5a16, although they
should have the same behavior as the -3 and -4 tests).

PR-URL: #33347
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
codebytere pushed a commit that referenced this pull request Jun 9, 2020
As the comment indicates, this fixes a DCHECK failure, although I don’t
quite understand why it is happening in the first place.

PR-URL: #33347
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
codebytere pushed a commit to codebytere/node that referenced this pull request Jun 9, 2020
Termination exceptions are similar to uncaught exceptions in that they
should clear the async id stack, because no ongoing async callbacks
will be brought to completion when execution terminates.

Previously, there was a check that made sure that that happened when
the termination occurred during the callback itself, but no such check
was in place for the case that the termination occurred during
microtasks started by them. This commit adds such a check, both for
microtasks and the `nextTick` queue. The latter addition doesn’t fix
a crash, but still makes sense conceptually.

The condition here is also flipped from applying only on Worker threads
to also applying on the main thread, and setting the `failed_` flag
rather than reading it. The former makes sense because the public C++
`Stop(env)` API can have the same effect as worker thread termination,
but on the main thread rather than a Worker thread.

PR-URL: nodejs#33347
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
codebytere pushed a commit that referenced this pull request Jun 9, 2020
Add regression tests for the case in which an async_hook is enabled
inside a Worker thread and `process.exit()` is called during the
async part of an async function.

This commit includes multiple tests that seem like they should all
crash in a similar way, but interestingly don’t. In particular, it’s
surprising that the presence of a statement after `process.exit()`
in a function has an effect on the kind of crash that’s being
exhibited (V8 DCHECK vs. assertion in our own code) and the
circumstances under which it crashes (e.g. the -1 and -2 tests
can be “fixed” by reverting 13c5a16, although they
should have the same behavior as the -3 and -4 tests).

PR-URL: #33347
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: David Carlier <devnexen@gmail.com>
@codebytere codebytere mentioned this pull request Jun 9, 2020
codebytere added a commit to electron/electron that referenced this pull request Jun 18, 2020
codebytere added a commit to electron/electron that referenced this pull request Jun 18, 2020
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. 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++. worker Issues and PRs related to Worker support.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants