From: Andreas Gampe Date: Tue, 4 Oct 2016 02:47:08 +0000 (-0700) Subject: ART: Reprint long messages on abort X-Git-Tag: android-x86-7.1-r1~14^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=47d522b27f;p=android-x86%2Fart.git ART: Reprint long messages on abort Add an abort message parameter to Runtime::Abort. In case the message is multiline (and will thus not be completely preserved in the Android abort reason), reprint the message after all threads have been dumped. Bug: 31893081 Test: m test-art-host Change-Id: I65bc77691fec79f7c868a90d6132805fcc91e473 (cherry picked from commit 90a32b16feb58d4edf932fdcb6a070be3418e365) --- diff --git a/runtime/base/logging.cc b/runtime/base/logging.cc index 212e5bd92..df8a3692a 100644 --- a/runtime/base/logging.cc +++ b/runtime/base/logging.cc @@ -193,6 +193,8 @@ LogMessage::LogMessage(const char* file, unsigned int line, LogSeverity severity } } LogMessage::~LogMessage() { + std::string msg; + if (!PrintDirectly(data_->GetSeverity()) && data_->GetSeverity() != LogSeverity::NONE) { if (data_->GetSeverity() < gMinimumLogSeverity) { return; // No need to format something we're not going to output. @@ -202,7 +204,7 @@ LogMessage::~LogMessage() { if (data_->GetError() != -1) { data_->GetBuffer() << ": " << strerror(data_->GetError()); } - std::string msg(data_->ToString()); + msg = data_->ToString(); // Do the actual logging with the lock held. { @@ -216,6 +218,8 @@ LogMessage::~LogMessage() { size_t nl = msg.find('\n', i); msg[nl] = '\0'; LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetSeverity(), &msg[i]); + // Undo zero-termination, so we retain the complete message. + msg[nl] = '\n'; i = nl + 1; } } @@ -224,7 +228,7 @@ LogMessage::~LogMessage() { // Abort if necessary. if (data_->GetSeverity() == FATAL) { - Runtime::Abort(); + Runtime::Abort(msg.c_str()); } } diff --git a/runtime/indirect_reference_table.cc b/runtime/indirect_reference_table.cc index f334a0553..06d376b86 100644 --- a/runtime/indirect_reference_table.cc +++ b/runtime/indirect_reference_table.cc @@ -129,15 +129,9 @@ IndirectRef IndirectReferenceTable::Add(uint32_t cookie, mirror::Object* obj) { DCHECK_GE(segment_state_.parts.numHoles, prevState.parts.numHoles); if (topIndex == max_entries_) { - std::ostringstream oss; - oss << "JNI ERROR (app bug): " << kind_ << " table overflow " - << "(max=" << max_entries_ << ")\n" - << MutatorLockedDumpable(*this); - if (VLOG_IS_ON(jni)) { - LOG(FATAL) << oss.str(); - } else { - LOG_FATAL_THIS_THREAD_ONLY(oss.str()); - } + LOG(FATAL) << "JNI ERROR (app bug): " << kind_ << " table overflow " + << "(max=" << max_entries_ << ")\n" + << MutatorLockedDumpable(*this); } // We know there's enough room in the table. Now we just need to find diff --git a/runtime/runtime.cc b/runtime/runtime.cc index dd94828d1..9da0268c2 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -406,7 +406,7 @@ struct AbortState { } }; -void Runtime::Abort() { +void Runtime::Abort(const char* msg) { gAborting++; // set before taking any locks // Ensure that we don't have multiple threads trying to abort at once, @@ -421,6 +421,12 @@ void Runtime::Abort() { AbortState state; LOG(INTERNAL_FATAL) << Dumpable(state); + // Sometimes we dump long messages, and the Android abort message only retains the first line. + // In those cases, just log the message again, to avoid logcat limits. + if (msg != nullptr && strchr(msg, '\n') != nullptr) { + LOG(INTERNAL_FATAL) << msg; + } + // Call the abort hook if we have one. if (Runtime::Current() != nullptr && Runtime::Current()->abort_ != nullptr) { LOG(INTERNAL_FATAL) << "Calling abort hook..."; diff --git a/runtime/runtime.h b/runtime/runtime.h index 38680aa68..3b72aa7b3 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -228,7 +228,7 @@ class Runtime { // Aborts semi-cleanly. Used in the implementation of LOG(FATAL), which most // callers should prefer. - NO_RETURN static void Abort() REQUIRES(!Locks::abort_lock_); + NO_RETURN static void Abort(const char* msg) REQUIRES(!Locks::abort_lock_); // Returns the "main" ThreadGroup, used when attaching user threads. jobject GetMainThreadGroup() const;