Merge "ART: Do not recursively abort when visiting locks in a bad state" into lmp-dev
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index 4c780ee..107efd7 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -979,7 +979,7 @@
 }
 
 void Monitor::VisitLocks(StackVisitor* stack_visitor, void (*callback)(mirror::Object*, void*),
-                         void* callback_context) {
+                         void* callback_context, bool abort_on_failure) {
   mirror::ArtMethod* m = stack_visitor->GetMethod();
   CHECK(m != NULL);
 
@@ -1012,10 +1012,19 @@
     return;  // No "tries" implies no synchronization, so no held locks to report.
   }
 
+  // Get the dex pc. If abort_on_failure is false, GetDexPc will not abort in the case it cannot
+  // find the dex pc, and instead return kDexNoIndex. Then bail out, as it indicates we have an
+  // inconsistent stack anyways.
+  uint32_t dex_pc = stack_visitor->GetDexPc(abort_on_failure);
+  if (!abort_on_failure && dex_pc == DexFile::kDexNoIndex) {
+    LOG(ERROR) << "Could not find dex_pc for " << PrettyMethod(m);
+    return;
+  }
+
   // Ask the verifier for the dex pcs of all the monitor-enter instructions corresponding to
   // the locks held in this stack frame.
   std::vector<uint32_t> monitor_enter_dex_pcs;
-  verifier::MethodVerifier::FindLocksAtDexPc(m, stack_visitor->GetDexPc(), &monitor_enter_dex_pcs);
+  verifier::MethodVerifier::FindLocksAtDexPc(m, dex_pc, &monitor_enter_dex_pcs);
   if (monitor_enter_dex_pcs.empty()) {
     return;
   }
diff --git a/runtime/monitor.h b/runtime/monitor.h
index ae14fc1..a94295a 100644
--- a/runtime/monitor.h
+++ b/runtime/monitor.h
@@ -88,8 +88,10 @@
 
   // Calls 'callback' once for each lock held in the single stack frame represented by
   // the current state of 'stack_visitor'.
+  // The abort_on_failure flag allows to not die when the state of the runtime is unorderly. This
+  // is necessary when we have already aborted but want to dump the stack as much as we can.
   static void VisitLocks(StackVisitor* stack_visitor, void (*callback)(mirror::Object*, void*),
-                         void* callback_context)
+                         void* callback_context, bool abort_on_failure = true)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static bool IsValidLockWord(LockWord lock_word);
diff --git a/runtime/thread.cc b/runtime/thread.cc
index eaa1a83..dbb42c9 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -907,7 +907,8 @@
         Monitor::DescribeWait(os, thread);
       }
       if (can_allocate) {
-        Monitor::VisitLocks(this, DumpLockedObject, &os);
+        // Visit locks, but do not abort on errors. This would trigger a nested abort.
+        Monitor::VisitLocks(this, DumpLockedObject, &os, false);
       }
     }