Skip to content

Commit

Permalink
async_hooks: clear async_id_stack for terminations in more places
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: David Carlier <[email protected]>
  • Loading branch information
addaleax authored and codebytere committed Jun 7, 2020
1 parent 60e2bcf commit d572d4c
Showing 1 changed file with 10 additions and 3 deletions.
13 changes: 10 additions & 3 deletions src/api/callback.cc
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,13 @@ void InternalCallbackScope::Close() {
closed_ = true;

if (!env_->can_call_into_js()) return;
if (failed_ && !env_->is_main_thread() && env_->is_stopping()) {
env_->async_hooks()->clear_async_id_stack();
}
auto perform_stopping_check = [&]() {
if (env_->is_stopping()) {
MarkAsFailed();
env_->async_hooks()->clear_async_id_stack();
}
};
perform_stopping_check();

if (!failed_ && async_context_.async_id != 0 && !skip_hooks_) {
AsyncWrap::EmitAfter(env_, async_context_.async_id);
Expand All @@ -109,6 +113,8 @@ void InternalCallbackScope::Close() {

if (!tick_info->has_tick_scheduled()) {
MicrotasksScope::PerformCheckpoint(env_->isolate());

perform_stopping_check();
}

// Make sure the stack unwound properly. If there are nested MakeCallback's
Expand Down Expand Up @@ -136,6 +142,7 @@ void InternalCallbackScope::Close() {
if (tick_callback->Call(env_->context(), process, 0, nullptr).IsEmpty()) {
failed_ = true;
}
perform_stopping_check();
}

MaybeLocal<Value> InternalMakeCallback(Environment* env,
Expand Down

0 comments on commit d572d4c

Please sign in to comment.