From a49b55b78844557b65a98e7a77dd26078157ed7f Mon Sep 17 00:00:00 2001 From: yangguo Date: Tue, 17 Feb 2015 03:44:31 -0800 Subject: [PATCH] Correctly propagate terminate exception in TryCall. BUG=v8:3892 LOG=Y Review URL: https://codereview.chromium.org/928193002 Cr-Commit-Position: refs/heads/master@{#26685} --- src/execution.cc | 13 ++++++----- test/cctest/test-thread-termination.cc | 30 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/execution.cc b/src/execution.cc index 9dfef372bc3..facd3add5fe 100644 --- a/src/execution.cc +++ b/src/execution.cc @@ -210,19 +210,18 @@ MaybeHandle Execution::TryCall(Handle func, DCHECK(catcher.HasCaught()); DCHECK(isolate->has_pending_exception()); DCHECK(isolate->external_caught_exception()); - if (exception_out != NULL) { - if (isolate->pending_exception() == - isolate->heap()->termination_exception()) { - is_termination = true; - } else { + if (isolate->pending_exception() == + isolate->heap()->termination_exception()) { + is_termination = true; + } else { + if (exception_out != NULL) { *exception_out = v8::Utils::OpenHandle(*catcher.Exception()); } } - isolate->OptionalRescheduleException(true); + isolate->OptionalRescheduleException(false); } DCHECK(!isolate->has_pending_exception()); - DCHECK(!isolate->external_caught_exception()); } if (is_termination) isolate->TerminateExecution(); return maybe_result; diff --git a/test/cctest/test-thread-termination.cc b/test/cctest/test-thread-termination.cc index d31b4131dfc..3095b83bdac 100644 --- a/test/cctest/test-thread-termination.cc +++ b/test/cctest/test-thread-termination.cc @@ -474,3 +474,33 @@ TEST(ErrorObjectAfterTermination) { // TODO(yangguo): crbug/403509. Check for empty handle instead. CHECK(error->IsUndefined()); } + + +void InnerTryCallTerminate(const v8::FunctionCallbackInfo& args) { + CHECK(!v8::V8::IsExecutionTerminating(args.GetIsolate())); + v8::Handle global = CcTest::global(); + v8::Handle loop = + v8::Handle::Cast(global->Get(v8_str("loop"))); + i::MaybeHandle result = + i::Execution::TryCall(v8::Utils::OpenHandle((*loop)), + v8::Utils::OpenHandle((*global)), 0, NULL, NULL); + CHECK(result.is_null()); + CHECK(v8::V8::IsExecutionTerminating(CcTest::isolate())); +} + + +TEST(TerminationInInnerTryCall) { + v8::Isolate* isolate = CcTest::isolate(); + v8::HandleScope scope(isolate); + v8::Handle global_template = CreateGlobalTemplate( + CcTest::isolate(), TerminateCurrentThread, DoLoopNoCall); + global_template->Set( + v8_str("inner_try_call_terminate"), + v8::FunctionTemplate::New(isolate, InnerTryCallTerminate)); + v8::Handle context = + v8::Context::New(CcTest::isolate(), NULL, global_template); + v8::Context::Scope context_scope(context); + v8::TryCatch try_catch; + CompileRun("inner_try_call_terminate()"); + CHECK(try_catch.HasTerminated()); +}