aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorprimiano@chromium.org <primiano@chromium.org>2015-08-17 10:32:26 +0000
committerprimiano@chromium.org <primiano@chromium.org>2015-08-17 10:32:26 +0000
commit6ea9219d8049606b8ab961444451b8172e8ef648 (patch)
tree62d50d4a5d015f48fd6bdd5ee5850ddf6b07f177
parent[microdump] Fix hw architecture indication in build fingerprint line (diff)
downloadbreakpad-6ea9219d8049606b8ab961444451b8172e8ef648.tar.xz
[microdump] Move microdump writes to the crash ring-buffer log
So far the microdump_writer dumped the log in logcat using the default system log. This is simple to achieve but has some drawbacks: 1. Creates spam in the system log, pushing back other eventual useful messages. 2. There is a high chance that the microdump gets lost if some log spam storm happens immediately after a crash and before the log is collected by the feedback client. 3. Since Android L, the logger is smartly throttling messages (to reduce logcat spam). Throttling brekpad logs defeats the all point of microdumps. This change is conceptually very simple. Replace the use of __android_log_write() with __android_log_buf_write(), which takes an extra bufID argument. The main drawback is that the __android_log_buf_write is not exported in the NDK and needs to be dynamically looked up via dlsym. This choice has been discussed and advocated by Android owners. See the internal bug b/21753476. BUG=chromium:512755 R=thestig@chromium.org Review URL: https://codereview.chromium.org/1286063003 . git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1490 4c0a9323-5329-0410-9bdc-e9ce6186880e
-rw-r--r--src/client/linux/handler/exception_handler.cc5
-rw-r--r--src/client/linux/log/log.cc38
-rw-r--r--src/client/linux/log/log.h14
-rw-r--r--src/client/linux/microdump_writer/microdump_writer.cc6
4 files changed, 60 insertions, 3 deletions
diff --git a/src/client/linux/handler/exception_handler.cc b/src/client/linux/handler/exception_handler.cc
index dca7e7f0..9b20fe25 100644
--- a/src/client/linux/handler/exception_handler.cc
+++ b/src/client/linux/handler/exception_handler.cc
@@ -233,6 +233,11 @@ ExceptionHandler::ExceptionHandler(const MinidumpDescriptor& descriptor,
!minidump_descriptor_.IsMicrodumpOnConsole())
minidump_descriptor_.UpdatePath();
+#if defined(__ANDROID__)
+ if (minidump_descriptor_.IsMicrodumpOnConsole())
+ logger::initializeCrashLogWriter();
+#endif
+
pthread_mutex_lock(&g_handler_stack_mutex_);
if (!g_handler_stack_)
g_handler_stack_ = new std::vector<ExceptionHandler*>;
diff --git a/src/client/linux/log/log.cc b/src/client/linux/log/log.cc
index 18635913..fc23aa6d 100644
--- a/src/client/linux/log/log.cc
+++ b/src/client/linux/log/log.cc
@@ -31,15 +31,51 @@
#if defined(__ANDROID__)
#include <android/log.h>
+#include <dlfcn.h>
#else
#include "third_party/lss/linux_syscall_support.h"
#endif
namespace logger {
+#if defined(__ANDROID__)
+namespace {
+
+// __android_log_buf_write() is not exported in the NDK and is being used by
+// dynamic runtime linking. Its declaration is taken from Android's
+// system/core/include/log/log.h.
+using AndroidLogBufferWriteFunc = int (*)(int bufID, int prio, const char *tag,
+ const char *text);
+const int kAndroidCrashLogId = 4; // From LOG_ID_CRASH in log.h.
+const char kAndroidLogTag[] = "google-breakpad";
+
+bool g_crash_log_initialized = false;
+AndroidLogBufferWriteFunc g_android_log_buf_write = nullptr;
+
+} // namespace
+
+void initializeCrashLogWriter() {
+ if (g_crash_log_initialized)
+ return;
+ g_android_log_buf_write = reinterpret_cast<AndroidLogBufferWriteFunc>(
+ dlsym(RTLD_DEFAULT, "__android_log_buf_write"));
+ g_crash_log_initialized = true;
+}
+
+int writeToCrashLog(const char* buf) {
+ // Try writing to the crash log ring buffer. If not available, fall back to
+ // the standard log buffer.
+ if (g_android_log_buf_write) {
+ return g_android_log_buf_write(kAndroidCrashLogId, ANDROID_LOG_FATAL,
+ kAndroidLogTag, buf);
+ }
+ return __android_log_write(ANDROID_LOG_FATAL, kAndroidLogTag, buf);
+}
+#endif
+
int write(const char* buf, size_t nbytes) {
#if defined(__ANDROID__)
- return __android_log_write(ANDROID_LOG_WARN, "google-breakpad", buf);
+ return __android_log_write(ANDROID_LOG_WARN, kAndroidLogTag, buf);
#else
return sys_write(2, buf, nbytes);
#endif
diff --git a/src/client/linux/log/log.h b/src/client/linux/log/log.h
index a50e30dc..f94bbd5f 100644
--- a/src/client/linux/log/log.h
+++ b/src/client/linux/log/log.h
@@ -36,6 +36,20 @@ namespace logger {
int write(const char* buf, size_t nbytes);
+// In the case of Android the log can be written to the default system log
+// (default behavior of write() above, or to the crash log (see
+// writeToCrashLog() below).
+#if defined(__ANDROID__)
+
+// The logger must be initialized in a non-compromised context.
+void initializeCrashLogWriter();
+
+// Once initialized, writeToCrashLog is safe to use in a compromised context,
+// even if the initialization failed, in which case this will silently fall
+// back on write().
+int writeToCrashLog(const char* buf);
+#endif
+
} // namespace logger
#endif // CLIENT_LINUX_LOG_LOG_H_
diff --git a/src/client/linux/microdump_writer/microdump_writer.cc b/src/client/linux/microdump_writer/microdump_writer.cc
index d54d4909..c2dba35b 100644
--- a/src/client/linux/microdump_writer/microdump_writer.cc
+++ b/src/client/linux/microdump_writer/microdump_writer.cc
@@ -105,9 +105,11 @@ class MicrodumpWriter {
private:
// Writes one line to the system log.
void LogLine(const char* msg) {
+#if defined(__ANDROID__)
+ logger::writeToCrashLog(msg);
+#else
logger::write(msg, my_strlen(msg));
-#if !defined(__ANDROID__)
- logger::write("\n", 1); // Android logger appends the \n. Linux's doesn't.
+ logger::write("\n", 1);
#endif
}