Commit 4ed9d48f authored by Sigurd Schneider's avatar Sigurd Schneider Committed by Commit Bot

[exceptions] Don't re-request interrupt in InvokeWithTryCatch

This CL changes InvokeWithTryCatch to not re-request the terminate
execution interrupt, but instead schedule the termination exception.
This ensures that leaving the outermost TryCatch scope will clear
the exception, and no interrupt remains.

Previously, the interrupt request could remain and prevent further
JavaScript execution even after the TryCatch scope was left.

Change-Id: I1e603dc822bbcb0def4cf0a898d59cf8d4b9d039
Bug: chromium:1014415
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1871910
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65255}
parent aaa5810f
......@@ -336,15 +336,17 @@ MaybeHandle<Object> InvokeWithTryCatch(Isolate* isolate,
DCHECK(isolate->external_caught_exception());
*params.exception_out = v8::Utils::OpenHandle(*catcher.Exception());
}
}
if (params.message_handling == Execution::MessageHandling::kReport) {
isolate->OptionalRescheduleException(true);
if (params.message_handling == Execution::MessageHandling::kReport) {
isolate->OptionalRescheduleException(true);
}
}
}
}
// Re-request terminate execution interrupt to trigger later.
if (is_termination) isolate->stack_guard()->RequestTerminateExecution();
if (is_termination) {
// Reschedule terminate execution exception.
isolate->OptionalRescheduleException(false);
}
return maybe_result;
}
......
......@@ -177,6 +177,7 @@ int MicrotaskQueue::RunMicrotasks(Isolate* isolate) {
capacity_ = 0;
size_ = 0;
start_ = 0;
DCHECK(isolate->has_scheduled_exception());
isolate->SetTerminationOnExternalTryCatch();
OnCompleted(isolate);
return -1;
......
......@@ -760,9 +760,9 @@ void InnerTryCallTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Utils::OpenHandle((*global)), 0, nullptr,
i::Execution::MessageHandling::kReport, &exception);
CHECK(result.is_null());
// TryCall ignores terminate execution, but rerequests the interrupt.
CHECK(!args.GetIsolate()->IsExecutionTerminating());
CHECK(CompileRun("1 + 1;").IsEmpty());
CHECK(exception.is_null());
// TryCall reschedules the termination exception.
CHECK(args.GetIsolate()->IsExecutionTerminating());
}
......@@ -781,7 +781,13 @@ TEST(TerminationInInnerTryCall) {
v8::TryCatch try_catch(isolate);
CompileRun("inner_try_call_terminate()");
CHECK(try_catch.HasTerminated());
// Any further exectutions in this TryCatch scope fail.
CHECK(isolate->IsExecutionTerminating());
CHECK(CompileRun("1 + 1").IsEmpty());
CHECK(CompileRun("1 + 1").IsEmpty());
CHECK(CompileRun("1 + 1").IsEmpty());
}
// Leaving the TryCatch cleared the termination exception.
v8::Maybe<int32_t> result =
CompileRun("2 + 2")->Int32Value(isolate->GetCurrentContext());
CHECK_EQ(4, result.FromJust());
......@@ -811,11 +817,14 @@ TEST(TerminateAndTryCall) {
->Get(isolate->GetCurrentContext(), v8_str("terminate"))
.ToLocalChecked();
CHECK(value->IsFunction());
// The first stack check after terminate has been re-requested fails.
// Any further executions in this TryCatch scope fail.
CHECK(!isolate->IsExecutionTerminating());
CHECK(CompileRun("1 + 1").IsEmpty());
CHECK(isolate->IsExecutionTerminating());
CHECK(CompileRun("1 + 1").IsEmpty());
CHECK(CompileRun("1 + 1").IsEmpty());
}
// V8 then recovers.
// Leaving the TryCatch cleared the termination exception.
v8::Maybe<int32_t> result =
CompileRun("2 + 2")->Int32Value(isolate->GetCurrentContext());
CHECK_EQ(4, result.FromJust());
......@@ -894,26 +903,36 @@ TEST(TerminateInMicrotask) {
isolate, TerminateCurrentThread, DoLoopCancelTerminate);
v8::Local<v8::Context> context1 = v8::Context::New(isolate, nullptr, global);
v8::Local<v8::Context> context2 = v8::Context::New(isolate, nullptr, global);
v8::TryCatch try_catch(isolate);
{
v8::Context::Scope context_scope(context1);
CHECK(!isolate->IsExecutionTerminating());
CHECK(!CompileRun("Promise.resolve().then(function() {"
"terminate(); loop(); fail();})")
.IsEmpty());
CHECK(!try_catch.HasCaught());
}
{
v8::Context::Scope context_scope(context2);
CHECK(context2 == isolate->GetCurrentContext());
CHECK(context2 == isolate->GetEnteredOrMicrotaskContext());
CHECK(!isolate->IsExecutionTerminating());
isolate->RunMicrotasks();
CHECK(context2 == isolate->GetCurrentContext());
CHECK(context2 == isolate->GetEnteredOrMicrotaskContext());
CHECK(try_catch.HasCaught());
CHECK(try_catch.HasTerminated());
v8::TryCatch try_catch(isolate);
{
v8::Context::Scope context_scope(context1);
CHECK(!isolate->IsExecutionTerminating());
CHECK(!CompileRun("Promise.resolve().then(function() {"
"terminate(); loop(); fail();})")
.IsEmpty());
CHECK(!try_catch.HasCaught());
}
{
v8::Context::Scope context_scope(context2);
CHECK(context2 == isolate->GetCurrentContext());
CHECK(context2 == isolate->GetEnteredOrMicrotaskContext());
CHECK(!isolate->IsExecutionTerminating());
isolate->RunMicrotasks();
CHECK(context2 == isolate->GetCurrentContext());
CHECK(context2 == isolate->GetEnteredOrMicrotaskContext());
CHECK(try_catch.HasCaught());
CHECK(try_catch.HasTerminated());
CHECK(isolate->IsExecutionTerminating());
CHECK(!CcTest::i_isolate()->stack_guard()->CheckTerminateExecution());
// Any further exectutions in this TryCatch scope fail.
CHECK(isolate->IsExecutionTerminating());
CHECK(CompileRun("1 + 1").IsEmpty());
CHECK(CompileRun("1 + 1").IsEmpty());
CHECK(CompileRun("1 + 1").IsEmpty());
}
}
CHECK(!CcTest::i_isolate()->stack_guard()->CheckTerminateExecution());
CHECK(!isolate->IsExecutionTerminating());
}
......@@ -932,8 +951,8 @@ TEST(TerminateInApiMicrotask) {
v8::Local<v8::ObjectTemplate> global = CreateGlobalTemplate(
isolate, TerminateCurrentThread, DoLoopCancelTerminate);
v8::Local<v8::Context> context = v8::Context::New(isolate, nullptr, global);
v8::TryCatch try_catch(isolate);
{
v8::TryCatch try_catch(isolate);
v8::Context::Scope context_scope(context);
CHECK(!isolate->IsExecutionTerminating());
isolate->EnqueueMicrotask(TerminationMicrotask);
......@@ -941,6 +960,7 @@ TEST(TerminateInApiMicrotask) {
isolate->RunMicrotasks();
CHECK(try_catch.HasCaught());
CHECK(try_catch.HasTerminated());
CHECK(isolate->IsExecutionTerminating());
}
CHECK(!isolate->IsExecutionTerminating());
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment