OSDN Git Service

ART: Stash any exception before dumping a stack
authorAndreas Gampe <agampe@google.com>
Fri, 3 Oct 2014 04:00:06 +0000 (21:00 -0700)
committerAndreas Gampe <agampe@google.com>
Fri, 3 Oct 2014 04:00:06 +0000 (21:00 -0700)
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
Change-Id: I3cd0526b52fce1acaa35fe0e419176478c82be22

runtime/thread.cc

index 6b65f12..482ba26 100644 (file)
@@ -978,10 +978,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<Thread*>(this));
+  Handle<mirror::Throwable> exc;
+  ThrowLocation exc_location;
+  bool have_exception = false;
+  if (IsExceptionPending()) {
+    exc = scope.NewHandle(GetException(&exc_location));
+    const_cast<Thread*>(this)->ClearException();
+    have_exception = true;
+  }
+
   std::unique_ptr<Context> context(Context::Create());
   StackDumpVisitor dumper(os, const_cast<Thread*>(this), context.get(),
                           !tls32_.throwing_OutOfMemoryError);
   dumper.WalkStack();
+
+  if (have_exception) {
+    const_cast<Thread*>(this)->SetException(exc_location, exc.Get());
+  }
 }
 
 void Thread::DumpStack(std::ostream& os) const {