ART: Use libbase logging
Move most of our logging infrastructure over to system/core/base.
Retain VLOG.
Using unified Android infrastructure has two main advantages. First,
it reduces the complexity/maintenance burden in ART. Second, it
allows to detach logging for the cases where we do not want or need
a runtime, e.g., dexdump, the disassembler, etc. As a part of the
latter, libbase is also supported for all hosts (including Windows).
From a developer viewpoint, there are minor behavior changes for the
LOG statements (see above), but otherwise usage is the same. Explicit
severity enum items are in the android::base namespace now.
Bug: 31338270
Test: m test-art-host
Change-Id: I5abcb2f45f5b03d49951874c48544f72a283a91b
diff --git a/runtime/base/logging.cc b/runtime/base/logging.cc
index e00e62d..17873b5 100644
--- a/runtime/base/logging.cc
+++ b/runtime/base/logging.cc
@@ -28,6 +28,7 @@
// Headers for LogMessage::LogLine.
#ifdef ART_TARGET_ANDROID
#include "cutils/log.h"
+#include <android/set_abort_message.h>
#else
#include <sys/types.h>
#include <unistd.h>
@@ -39,24 +40,10 @@
unsigned int gAborting = 0;
-static LogSeverity gMinimumLogSeverity = INFO;
static std::unique_ptr<std::string> gCmdLine;
static std::unique_ptr<std::string> gProgramInvocationName;
static std::unique_ptr<std::string> gProgramInvocationShortName;
-// Print INTERNAL_FATAL messages directly instead of at destruction time. This only works on the
-// host right now: for the device, a stream buf collating output into lines and calling LogLine or
-// lower-level logging is necessary.
-#ifdef ART_TARGET_ANDROID
-static constexpr bool kPrintInternalFatalDirectly = false;
-#else
-static constexpr bool kPrintInternalFatalDirectly = !kIsTargetBuild;
-#endif
-
-static bool PrintDirectly(LogSeverity severity) {
- return kPrintInternalFatalDirectly && severity == INTERNAL_FATAL;
-}
-
const char* GetCmdLine() {
return (gCmdLine.get() != nullptr) ? gCmdLine->c_str() : nullptr;
}
@@ -70,6 +57,16 @@
: "art";
}
+NO_RETURN
+static void RuntimeAborter(const char* abort_message) {
+#ifdef __ANDROID__
+ android_set_abort_message(abort_message);
+#else
+ UNUSED(abort_message);
+#endif
+ Runtime::Abort();
+}
+
void InitLogging(char* argv[]) {
if (gCmdLine.get() != nullptr) {
return;
@@ -94,150 +91,14 @@
// TODO: fall back to /proc/self/cmdline when argv is null on Linux.
gCmdLine.reset(new std::string("<unset>"));
}
- const char* tags = getenv("ANDROID_LOG_TAGS");
- if (tags == nullptr) {
- return;
- }
- std::vector<std::string> specs;
- Split(tags, ' ', &specs);
- for (size_t i = 0; i < specs.size(); ++i) {
- // "tag-pattern:[vdiwefs]"
- std::string spec(specs[i]);
- if (spec.size() == 3 && StartsWith(spec, "*:")) {
- switch (spec[2]) {
- case 'v':
- gMinimumLogSeverity = VERBOSE;
- continue;
- case 'd':
- gMinimumLogSeverity = DEBUG;
- continue;
- case 'i':
- gMinimumLogSeverity = INFO;
- continue;
- case 'w':
- gMinimumLogSeverity = WARNING;
- continue;
- case 'e':
- gMinimumLogSeverity = ERROR;
- continue;
- case 'f':
- gMinimumLogSeverity = FATAL;
- continue;
- // liblog will even suppress FATAL if you say 's' for silent, but that's crazy!
- case 's':
- gMinimumLogSeverity = FATAL;
- continue;
- }
- }
- LOG(FATAL) << "unsupported '" << spec << "' in ANDROID_LOG_TAGS (" << tags << ")";
- }
-}
-
-// This indirection greatly reduces the stack impact of having
-// lots of checks/logging in a function.
-class LogMessageData {
- public:
- LogMessageData(const char* file, unsigned int line, LogSeverity severity, int error)
- : file_(GetFilenameBase(file)),
- line_number_(line),
- severity_(severity),
- error_(error) {}
-
- const char * GetFile() const {
- return file_;
- }
-
- unsigned int GetLineNumber() const {
- return line_number_;
- }
-
- LogSeverity GetSeverity() const {
- return severity_;
- }
-
- int GetError() const {
- return error_;
- }
-
- std::ostream& GetBuffer() {
- return buffer_;
- }
-
- std::string ToString() const {
- return buffer_.str();
- }
-
- private:
- std::ostringstream buffer_;
- const char* const file_;
- const unsigned int line_number_;
- const LogSeverity severity_;
- const int error_;
-
- static const char* GetFilenameBase(const char* file) {
- const char* last_slash = strrchr(file, '/');
- return (last_slash == nullptr) ? file : last_slash + 1;
- }
-
- DISALLOW_COPY_AND_ASSIGN(LogMessageData);
-};
-
-
-LogMessage::LogMessage(const char* file, unsigned int line, LogSeverity severity, int error)
- : data_(new LogMessageData(file, line, severity, error)) {
- if (PrintDirectly(severity)) {
- static constexpr char kLogCharacters[] = { 'V', 'D', 'I', 'W', 'E', 'F', 'F' };
- static_assert(arraysize(kLogCharacters) == static_cast<size_t>(INTERNAL_FATAL) + 1,
- "Wrong character array size");
- stream() << ProgramInvocationShortName() << " " << kLogCharacters[static_cast<size_t>(severity)]
- << " " << getpid() << " " << ::art::GetTid() << " " << file << ":" << line << "]";
- }
-}
-LogMessage::~LogMessage() {
- if (PrintDirectly(data_->GetSeverity())) {
- // Add newline at the end to match the not printing directly behavior.
- std::cerr << '\n';
- } else {
- if (data_->GetSeverity() < gMinimumLogSeverity) {
- return; // No need to format something we're not going to output.
- }
-
- // Finish constructing the message.
- if (data_->GetError() != -1) {
- data_->GetBuffer() << ": " << strerror(data_->GetError());
- }
- std::string msg(data_->ToString());
-
- // Do the actual logging with the lock held.
- {
- MutexLock mu(Thread::Current(), *Locks::logging_lock_);
- if (msg.find('\n') == std::string::npos) {
- LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetSeverity(), msg.c_str());
- } else {
- msg += '\n';
- size_t i = 0;
- while (i < msg.size()) {
- size_t nl = msg.find('\n', i);
- msg[nl] = '\0';
- LogLine(data_->GetFile(), data_->GetLineNumber(), data_->GetSeverity(), &msg[i]);
- i = nl + 1;
- }
- }
- }
- }
-
- // Abort if necessary.
- if (data_->GetSeverity() == FATAL) {
- Runtime::Abort();
- }
-}
-
-std::ostream& LogMessage::stream() {
- if (PrintDirectly(data_->GetSeverity())) {
- return std::cerr;
- }
- return data_->GetBuffer();
+#ifdef __ANDROID__
+#define INIT_LOGGING_DEFAULT_LOGGER android::base::LogdLogger()
+#else
+#define INIT_LOGGING_DEFAULT_LOGGER android::base::StderrLogger
+#endif
+ android::base::InitLogging(argv, INIT_LOGGING_DEFAULT_LOGGER, RuntimeAborter);
+#undef INIT_LOGGING_DEFAULT_LOGGER
}
#ifdef ART_TARGET_ANDROID
@@ -245,31 +106,14 @@
ANDROID_LOG_VERBOSE, ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN,
ANDROID_LOG_ERROR, ANDROID_LOG_FATAL, ANDROID_LOG_FATAL
};
-static_assert(arraysize(kLogSeverityToAndroidLogPriority) == INTERNAL_FATAL + 1,
+static_assert(arraysize(kLogSeverityToAndroidLogPriority) == ::android::base::FATAL + 1,
"Mismatch in size of kLogSeverityToAndroidLogPriority and values in LogSeverity");
#endif
-void LogMessage::LogLine(const char* file, unsigned int line, LogSeverity log_severity,
- const char* message) {
-#ifdef ART_TARGET_ANDROID
- const char* tag = ProgramInvocationShortName();
- int priority = kLogSeverityToAndroidLogPriority[static_cast<size_t>(log_severity)];
- if (priority == ANDROID_LOG_FATAL) {
- LOG_PRI(priority, tag, "%s:%u] %s", file, line, message);
- } else {
- LOG_PRI(priority, tag, "%s", message);
- }
-#else
- static const char* log_characters = "VDIWEFF";
- CHECK_EQ(strlen(log_characters), INTERNAL_FATAL + 1U);
- char severity = log_characters[log_severity];
- fprintf(stderr, "%s %c %5d %5d %s:%u] %s\n",
- ProgramInvocationShortName(), severity, getpid(), ::art::GetTid(), file, line, message);
-#endif
-}
-
-void LogMessage::LogLineLowStack(const char* file, unsigned int line, LogSeverity log_severity,
- const char* message) {
+void LogHelper::LogLineLowStack(const char* file,
+ unsigned int line,
+ LogSeverity log_severity,
+ const char* message) {
#ifdef ART_TARGET_ANDROID
// Use android_writeLog() to avoid stack-based buffers used by android_printLog().
const char* tag = ProgramInvocationShortName();
@@ -292,8 +136,9 @@
}
#else
static constexpr char kLogCharacters[] = { 'V', 'D', 'I', 'W', 'E', 'F', 'F' };
- static_assert(arraysize(kLogCharacters) == static_cast<size_t>(INTERNAL_FATAL) + 1,
- "Wrong character array size");
+ static_assert(
+ arraysize(kLogCharacters) == static_cast<size_t>(::android::base::FATAL) + 1,
+ "Wrong character array size");
const char* program_name = ProgramInvocationShortName();
TEMP_FAILURE_RETRY(write(STDERR_FILENO, program_name, strlen(program_name)));
@@ -310,13 +155,4 @@
#endif // ART_TARGET_ANDROID
}
-ScopedLogSeverity::ScopedLogSeverity(LogSeverity level) {
- old_ = gMinimumLogSeverity;
- gMinimumLogSeverity = level;
-}
-
-ScopedLogSeverity::~ScopedLogSeverity() {
- gMinimumLogSeverity = old_;
-}
-
} // namespace art