From 986c6fbb5f65006165f8b7fed1fd105fb3a83bd9 Mon Sep 17 00:00:00 2001 From: Andreas Gampe Date: Thu, 2 Oct 2014 21:00:06 -0700 Subject: ART: Stash any exception before dumping a stack Dumping a managed stack entails dumping held locks, in the process of which the verifier will be run. The verifier works under the assumption that there were no exceptions when started. This assumption is violated for example on certain JNI aborts. The solution is to stash any pending exception before dumping the stack, and re-installing it afterwards. Bug: 17669899 (cherry picked from commit d87bc135dba41f0f21cf0018a3b2cb46809890d7) Change-Id: Ic44780bad90a8e1ba80858c807e2bef3bf6651c6 --- runtime/thread.cc | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/runtime/thread.cc b/runtime/thread.cc index b0c8fe1b3a..d573a3f724 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -947,10 +947,27 @@ static bool ShouldShowNativeStack(const Thread* thread) } void Thread::DumpJavaStack(std::ostream& os) const { + // Dumping the Java stack involves the verifier for locks. The verifier operates under the + // assumption that there is no exception pending on entry. Thus, stash any pending exception. + // TODO: Find a way to avoid const_cast. + StackHandleScope<1> scope(const_cast(this)); + Handle exc; + ThrowLocation exc_location; + bool have_exception = false; + if (IsExceptionPending()) { + exc = scope.NewHandle(GetException(&exc_location)); + const_cast(this)->ClearException(); + have_exception = true; + } + std::unique_ptr context(Context::Create()); StackDumpVisitor dumper(os, const_cast(this), context.get(), !tls32_.throwing_OutOfMemoryError); dumper.WalkStack(); + + if (have_exception) { + const_cast(this)->SetException(exc_location, exc.Get()); + } } void Thread::DumpStack(std::ostream& os) const { -- cgit v1.2.3-59-g8ed1b