diff options
-rw-r--r-- | runtime/jit/jit.cc | 9 | ||||
-rw-r--r-- | runtime/runtime.cc | 17 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.cc | 14 |
3 files changed, 33 insertions, 7 deletions
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc index 803e9d5e61..dac2e60987 100644 --- a/runtime/jit/jit.cc +++ b/runtime/jit/jit.cc @@ -274,6 +274,15 @@ bool Jit::CompileMethod(ArtMethod* method, Thread* self, bool osr) { << ArtMethod::PrettyMethod(method_to_compile) << " osr=" << std::boolalpha << osr; } + if (kIsDebugBuild) { + if (self->IsExceptionPending()) { + mirror::Throwable* exception = self->GetException(); + LOG(FATAL) << "No pending exception expected after compiling " + << ArtMethod::PrettyMethod(method) + << ": " + << exception->Dump(); + } + } return success; } diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 771ac273fa..1490f05a75 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -372,9 +372,7 @@ struct AbortState { void Dump(std::ostream& os) const { if (gAborting > 1) { os << "Runtime aborting --- recursively, so no thread-specific detail!\n"; - if (gAborting == 2) { - DumpRecursiveAbort(os); - } + DumpRecursiveAbort(os); return; } gAborting++; @@ -434,8 +432,17 @@ struct AbortState { // For recursive aborts. void DumpRecursiveAbort(std::ostream& os) const NO_THREAD_SAFETY_ANALYSIS { - // The only thing we'll attempt is dumping the native stack of the current thread. - DumpNativeStack(os, GetTid()); + // The only thing we'll attempt is dumping the native stack of the current thread. We will only + // try this if we haven't exceeded an arbitrary amount of recursions, to recover and actually + // die. + // Note: as we're using a global counter for the recursive abort detection, there is a potential + // race here and it is not OK to just print when the counter is "2" (one from + // Runtime::Abort(), one from previous Dump() call). Use a number that seems large enough. + static constexpr size_t kOnlyPrintWhenRecursionLessThan = 100u; + if (gAborting < kOnlyPrintWhenRecursionLessThan) { + gAborting++; + DumpNativeStack(os, GetTid()); + } } }; diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index d9e3ea7a0d..ed24611801 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -100,8 +100,18 @@ PcToRegisterLineTable::~PcToRegisterLineTable() {} ALWAYS_INLINE static inline bool FailOrAbort(MethodVerifier* verifier, bool condition, const char* error_msg, uint32_t work_insn_idx) { if (kIsDebugBuild) { - // In a debug build, abort if the error condition is wrong. - DCHECK(condition) << error_msg << work_insn_idx; + // In a debug build, abort if the error condition is wrong. Only warn if + // we are already aborting (as this verification is likely run to print + // lock information). + if (LIKELY(gAborting == 0)) { + DCHECK(condition) << error_msg << work_insn_idx; + } else { + if (!condition) { + LOG(ERROR) << error_msg << work_insn_idx; + verifier->Fail(VERIFY_ERROR_BAD_CLASS_HARD) << error_msg << work_insn_idx; + return true; + } + } } else { // In a non-debug build, just fail the class. if (!condition) { |