Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(24)

Unified Diff: chrome/app/breakpad_posix.cc

Issue 9838033: Upstream native crash handling changes for Android. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Chrome Android native crash support Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/app/breakpad_posix.cc
diff --git a/chrome/app/breakpad_linux.cc b/chrome/app/breakpad_posix.cc
similarity index 86%
rename from chrome/app/breakpad_linux.cc
rename to chrome/app/breakpad_posix.cc
index eff3a12bea23760acdad75459bb69b2abd0f891a..2e4273cf17dae4bb56850c01a8694b9b752abfb9 100644
--- a/chrome/app/breakpad_linux.cc
+++ b/chrome/app/breakpad_posix.cc
@@ -43,6 +43,16 @@
#include "content/common/chrome_descriptors.h"
#include "seccompsandbox/linux_syscall_support.h"
+#ifdef OS_ANDROID
+#include <android/log.h>
+#include <sys/stat.h>
+#include "base/android/path_utils.h"
+#include "base/android/build_info.h"
+#include "third_party/lss/linux_syscall_support.h"
+#else
+#include "seccompsandbox/linux_syscall_support.h"
+#endif
+
#ifndef PR_SET_PTRACER
#define PR_SET_PTRACER 0x59616d61
#endif
@@ -114,6 +124,33 @@ static void my_uint64tos(char* output, uint64_t i, unsigned i_len) {
output[index - 1] = '0' + (i % 10);
}
+static char* my_strncpy(char* dst, const char* src, size_t len) {
+ int i = len;
+ char* p = dst;
+ if (!dst || !src)
+ return dst;
+ while (i != 0 && *src != '\0') {
+ *p++ = *src++;
+ i--;
+ }
+ while (i != 0) {
+ *p++ = '\0';
+ i--;
+ }
+ return dst;
+}
+
+static char* my_strncat(char *dest, const char *src, size_t len) {
+ char *ret = dest;
+ while (*dest)
+ dest++;
+ while (len--)
+ if (!(*dest++ = *src++))
+ return ret;
+ *dest = 0;
+ return ret;
+}
+
namespace {
// MIME substrings.
@@ -301,8 +338,24 @@ void DumpProcess() {
g_breakpad->WriteMinidump();
}
+size_t log(const char* buf, size_t nbytes) {
Yaron 2012/03/26 18:51:16 Woah. Why is log defined twice? Also, you're alrea
carlosvaldivia 2012/04/03 06:24:47 Mistake. Fixed. On 2012/03/26 18:51:16, Yaron wro
+#if defined(OS_ANDROID)
+ return __android_log_write(ANDROID_LOG_WARN, "google-breakpad", buf);
+#else
+ return sys_write(2, buf, nbytes)
+#endif
+}
+
} // namespace
+void log(const char* buf, size_t nbytes) {
+#if defined(OS_ANDROID)
+ return __android_log_write(ANDROID_LOG_WARN, "google-breakpad", buf);
+#else
+ return sys_write(2, buf, nbytes)
+#endif
+}
+
void HandleCrashDump(const BreakpadInfo& info) {
// WARNING: this code runs in a compromised context. It may not call into
// libc nor allocate memory normally.
@@ -310,13 +363,18 @@ void HandleCrashDump(const BreakpadInfo& info) {
const int dumpfd = sys_open(info.filename, O_RDONLY, 0);
if (dumpfd < 0) {
static const char msg[] = "Cannot upload crash dump: failed to open\n";
- sys_write(2, msg, sizeof(msg));
+ log(msg, sizeof(msg));
return;
}
+#if defined(OS_ANDROID)
+ struct stat st;
+ if (fstat(dumpfd, &st) != 0) {
+#else
struct kernel_stat st;
if (sys_fstat(dumpfd, &st) != 0) {
+#endif
static const char msg[] = "Cannot upload crash dump: stat failed\n";
- sys_write(2, msg, sizeof(msg));
+ log(msg, sizeof(msg));
IGNORE_RET(sys_close(dumpfd));
return;
}
@@ -326,7 +384,7 @@ void HandleCrashDump(const BreakpadInfo& info) {
uint8_t* dump_data = reinterpret_cast<uint8_t*>(allocator.Alloc(st.st_size));
if (!dump_data) {
static const char msg[] = "Cannot upload crash dump: cannot alloc\n";
- sys_write(2, msg, sizeof(msg));
+ log(msg, sizeof(msg));
IGNORE_RET(sys_close(dumpfd));
return;
}
@@ -341,7 +399,7 @@ void HandleCrashDump(const BreakpadInfo& info) {
if (ufd < 0) {
static const char msg[] = "Cannot upload crash dump because /dev/urandom"
" is missing\n";
- sys_write(2, msg, sizeof(msg) - 1);
+ log(msg, sizeof(msg) - 1);
return;
}
@@ -365,7 +423,7 @@ void HandleCrashDump(const BreakpadInfo& info) {
if (temp_file_fd < 0) {
static const char msg[] = "Failed to create temporary file in /tmp: "
"cannot upload crash dump\n";
- sys_write(2, msg, sizeof(msg) - 1);
+ log(msg, sizeof(msg) - 1);
IGNORE_RET(sys_close(ufd));
return;
}
@@ -373,7 +431,7 @@ void HandleCrashDump(const BreakpadInfo& info) {
temp_file_fd = sys_open(info.filename, O_WRONLY, 0600);
if (temp_file_fd < 0) {
static const char msg[] = "Failed to save crash dump: failed to open\n";
- sys_write(2, msg, sizeof(msg) - 1);
+ log(msg, sizeof(msg) - 1);
IGNORE_RET(sys_close(ufd));
return;
}
@@ -462,12 +520,26 @@ void HandleCrashDump(const BreakpadInfo& info) {
MimeWriter writer(temp_file_fd, mime_boundary);
{
-#if defined(OS_CHROMEOS)
+#if defined(OS_ANDROID)
+ static const char chrome_product_msg[] = "Chrome_Android";
+#elif defined(OS_CHROMEOS)
static const char chrome_product_msg[] = "Chrome_ChromeOS";
#else // OS_LINUX
static const char chrome_product_msg[] = "Chrome_Linux";
#endif
+
+#if defined (OS_ANDROID)
+ const base::android::BuildInfo* android_build_info =
+ base::android::BuildInfo::GetInstance();
+ static const char* version_msg = android_build_info->package_version_code;
+ static const char android_build_id[] = "android_build_id";
+ static const char android_build_fp[] = "android_build_fp";
+ static const char device[] = "device";
+ static const char model[] = "model";
+ static const char brand[] = "brand";
+#else
static const char version_msg[] = PRODUCT_VERSION;
+#endif
writer.AddBoundary();
writer.AddPairString("prod", chrome_product_msg);
@@ -476,6 +548,28 @@ void HandleCrashDump(const BreakpadInfo& info) {
writer.AddBoundary();
writer.AddPairString("guid", info.guid);
writer.AddBoundary();
+ if (info.pid > 0) {
+ uint64_t pid_str_len = my_uint64_len(info.pid);
+ char* pid_buf = reinterpret_cast<char*>(allocator.Alloc(pid_str_len));
+ my_uint64tos(pid_buf, info.pid, pid_str_len);
+ writer.AddPairString("pid", pid_buf);
+ writer.AddBoundary();
+ }
+#if defined(OS_ANDROID)
+ // Addtional MIME blocks are added for logging on Android devices.
+ writer.AddPairString(
+ android_build_id, android_build_info->android_build_id);
+ writer.AddBoundary();
+ writer.AddPairString(
+ android_build_fp, android_build_info->android_build_fp);
+ writer.AddBoundary();
+ writer.AddPairString(device, android_build_info->device);
+ writer.AddBoundary();
+ writer.AddPairString(model, android_build_info->model);
+ writer.AddBoundary();
+ writer.AddPairString(brand, android_build_info->brand);
+ writer.AddBoundary();
+#endif
writer.Flush();
}
@@ -612,6 +706,35 @@ void HandleCrashDump(const BreakpadInfo& info) {
writer.Flush();
IGNORE_RET(sys_close(temp_file_fd));
+#if defined(OS_ANDROID)
+ uint64_t pid_str_len = my_uint64_len(info.pid);
+ char* pid_buf = reinterpret_cast<char*>(allocator.Alloc(pid_str_len));
+ my_uint64tos(pid_buf, info.pid, pid_str_len);
+
+ static const char* output_msg = "Output crash dump file:";
+ log(output_msg, my_strlen(output_msg));
+ log(info.filename, info.filename_length);
+ // -1 because we won't need the null terminator on the original filename.
+ size_t done_filename_len = info.filename_length -1 + pid_str_len;
+ char* done_filename = reinterpret_cast<char*>(
+ allocator.Alloc(done_filename_len));
+ // Rename the file such that the pid is the suffix in order signal to other
+ // processes that the minidump is complete. The advantage of using the pid as
+ // the suffix is that it is trivial to associate the minidump with the
+ // crashed process.
+ // Finally, note strncpy prevents null terminators from
+ // being copied. Pad the rest with 0's.
+ my_strncpy(done_filename, info.filename, done_filename_len);
+ // Append the suffix a null terminator should be added.
+ my_strncat(done_filename, pid_buf, pid_str_len);
+ // Rename the minidump file to signal that it is complete.
+ if (rename(info.filename, done_filename)) {
+ __android_log_write(ANDROID_LOG_WARN, "chromium", "Failed to rename:");
+ __android_log_write(ANDROID_LOG_WARN, "chromium", info.filename);
+ __android_log_write(ANDROID_LOG_WARN, "chromium", "to");
+ __android_log_write(ANDROID_LOG_WARN, "chromium", done_filename);
+ }
+#endif
if (!info.upload)
return;
@@ -693,7 +816,7 @@ void HandleCrashDump(const BreakpadInfo& info) {
execve(kWgetBinary, const_cast<char**>(args), environ);
static const char msg[] = "Cannot upload crash dump: cannot exec "
"/usr/bin/wget\n";
- sys_write(2, msg, sizeof(msg) - 1);
+ log(msg, sizeof(msg) - 1);
sys__exit(1);
}
@@ -723,9 +846,9 @@ void HandleCrashDump(const BreakpadInfo& info) {
// Write crash dump id to stderr.
id_buf[len] = 0;
static const char msg[] = "\nCrash dump id: ";
- sys_write(2, msg, sizeof(msg) - 1);
- sys_write(2, id_buf, my_strlen(id_buf));
- sys_write(2, "\n", 1);
+ log(msg, sizeof(msg) - 1);
+ log(id_buf, my_strlen(id_buf));
+ log("\n", 1);
// Write crash dump id to crash log as: seconds_since_epoch,crash_id
struct kernel_timeval tv;
@@ -799,6 +922,7 @@ static bool CrashDone(const char* dump_path,
info.distro_length = my_strlen(base::g_linux_distro);
info.upload = upload;
info.process_start_time = g_process_start_time;
+ info.pid = 0;
HandleCrashDump(info);
return true;
}
@@ -811,6 +935,7 @@ static bool CrashDoneNoUpload(const char* dump_path,
return CrashDone(dump_path, minidump_id, false, succeeded);
}
+#if !defined(OS_ANDROID)
// Wrapper function, do not add more code here.
static bool CrashDoneUpload(const char* dump_path,
const char* minidump_id,
@@ -818,6 +943,7 @@ static bool CrashDoneUpload(const char* dump_path,
bool succeeded) {
return CrashDone(dump_path, minidump_id, true, succeeded);
}
+#endif
void EnableCrashDumping(const bool unattended) {
g_is_crash_reporter_enabled = true;
@@ -834,7 +960,12 @@ void EnableCrashDumping(const bool unattended) {
g_crash_log_path = new char[crash_log_path_len];
strncpy(g_crash_log_path, logfile_str.c_str(), crash_log_path_len);
}
-
+#if defined(OS_ANDROID)
+ // In Android we never upload from native code.
+ new google_breakpad::ExceptionHandler(dumps_path.value().c_str(), NULL,
Yaron 2012/03/26 18:51:16 Seems like you could still assign to g_breakpad an
carlosvaldivia 2012/04/03 06:24:47 Done.
+ CrashDoneNoUpload, NULL,
+ true /* install handlers */);
+#else
DCHECK(!g_breakpad);
if (unattended) {
g_breakpad = new google_breakpad::ExceptionHandler(
@@ -851,6 +982,7 @@ void EnableCrashDumping(const bool unattended) {
NULL,
true /* install handlers */);
}
+#endif
}
// Non-Browser = Extension, Gpu, Plugins, Ppapi and Renderer
@@ -861,7 +993,7 @@ static bool NonBrowserCrashHandler(const void* crash_context,
int fds[2] = { -1, -1 };
if (sys_socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
static const char msg[] = "Failed to create socket for crash dumping.\n";
- sys_write(2, msg, sizeof(msg)-1);
+ log(msg, sizeof(msg)-1);
return false;
}
@@ -936,7 +1068,7 @@ static bool NonBrowserCrashHandler(const void* crash_context,
if (HANDLE_EINTR(sys_sendmsg(fd, &msg, 0)) < 0) {
static const char errmsg[] = "Failed to tell parent about crash.\n";
- sys_write(2, errmsg, sizeof(errmsg)-1);
+ log(errmsg, sizeof(errmsg)-1);
IGNORE_RET(sys_close(fds[1]));
return false;
}
@@ -944,7 +1076,7 @@ static bool NonBrowserCrashHandler(const void* crash_context,
if (HANDLE_EINTR(sys_read(fds[0], &b, 1)) != 1) {
static const char errmsg[] = "Parent failed to complete crash dump.\n";
- sys_write(2, errmsg, sizeof(errmsg)-1);
+ log(errmsg, sizeof(errmsg)-1);
}
return true;
@@ -961,6 +1093,11 @@ void EnableNonBrowserCrashDumping() {
}
void InitCrashReporter() {
+#if defined(OS_ANDROID)
+ // This will guarantee that the BuildInfo has been initialized and subsequent
+ // calls will not require memory allocation.
+ base::android::BuildInfo::GetInstance();
+#endif
// Determine the process type and take appropriate action.
const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
if (parsed_command_line.HasSwitch(switches::kDisableBreakpad))
@@ -975,6 +1112,9 @@ void InitCrashReporter() {
process_type == switches::kPpapiPluginProcess ||
process_type == switches::kZygoteProcess ||
process_type == switches::kGpuProcess) {
+#if defined(OS_ANDROID)
+ child_process_logging::SetClientId("Android");
+#endif
// We might be chrooted in a zygote or renderer process so we cannot call
// GetCollectStatsConsent because that needs access the the user's home
// dir. Instead, we set a command line flag for these processes.

Powered by Google App Engine
This is Rietveld 408576698