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

Side by Side 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: 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // For linux_syscall_support.h. This makes it safe to call embedded system 5 // For linux_syscall_support.h. This makes it safe to call embedded system
6 // calls when in seccomp mode. 6 // calls when in seccomp mode.
7 #define SYS_SYSCALL_ENTRYPOINT "playground$syscallEntryPoint" 7 #define SYS_SYSCALL_ENTRYPOINT "playground$syscallEntryPoint"
8 8
9 #include "chrome/app/breakpad_linux.h" 9 #include "chrome/app/breakpad_linux.h"
10 10
(...skipping 23 matching lines...) Expand all
34 #include "breakpad/src/common/linux/linux_libc_support.h" 34 #include "breakpad/src/common/linux/linux_libc_support.h"
35 #include "breakpad/src/common/memory.h" 35 #include "breakpad/src/common/memory.h"
36 #include "chrome/browser/crash_upload_list.h" 36 #include "chrome/browser/crash_upload_list.h"
37 #include "chrome/common/child_process_logging.h" 37 #include "chrome/common/child_process_logging.h"
38 #include "chrome/common/chrome_paths.h" 38 #include "chrome/common/chrome_paths.h"
39 #include "chrome/common/chrome_switches.h" 39 #include "chrome/common/chrome_switches.h"
40 #include "chrome/common/chrome_version_info_posix.h" 40 #include "chrome/common/chrome_version_info_posix.h"
41 #include "chrome/common/env_vars.h" 41 #include "chrome/common/env_vars.h"
42 #include "chrome/common/logging_chrome.h" 42 #include "chrome/common/logging_chrome.h"
43 #include "content/common/chrome_descriptors.h" 43 #include "content/common/chrome_descriptors.h"
44 #include "seccompsandbox/linux_syscall_support.h" 44 #include "seccompsandbox/linux_syscall_support.h"
Yaron 2012/03/26 18:51:15 Remove this include if it shouldn't be in the andr
carlosvaldivia 2012/04/03 06:24:47 Done.
45 45
46 #ifdef OS_ANDROID
Yaron 2012/03/26 18:51:15 Nit: preferred style is #if defined(OS_ANDROID)
carlosvaldivia 2012/04/03 06:24:47 Done.
47 #include <android/log.h>
48 #include <sys/stat.h>
49 #include "base/android/path_utils.h"
50 #include "base/android/build_info.h"
51 #include "third_party/lss/linux_syscall_support.h"
52 #else
53 #include "seccompsandbox/linux_syscall_support.h"
54 #endif
55
46 #ifndef PR_SET_PTRACER 56 #ifndef PR_SET_PTRACER
47 #define PR_SET_PTRACER 0x59616d61 57 #define PR_SET_PTRACER 0x59616d61
48 #endif 58 #endif
49 59
50 // Some versions of gcc are prone to warn about unused return values. In cases 60 // Some versions of gcc are prone to warn about unused return values. In cases
51 // where we either a) know the call cannot fail, or b) there is nothing we 61 // where we either a) know the call cannot fail, or b) there is nothing we
52 // can do when a call fails, we mark the return code as ignored. This avoids 62 // can do when a call fails, we mark the return code as ignored. This avoids
53 // spurious compiler warnings. 63 // spurious compiler warnings.
54 #define IGNORE_RET(x) do { if (x); } while (0) 64 #define IGNORE_RET(x) do { if (x); } while (0)
55 65
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 } 117 }
108 118
109 // uint64_t version of my_itos() from 119 // uint64_t version of my_itos() from
110 // breakpad/src/common/linux/linux_libc_support.h. Convert a non-negative 120 // breakpad/src/common/linux/linux_libc_support.h. Convert a non-negative
111 // integer to a string (not null-terminated). 121 // integer to a string (not null-terminated).
112 static void my_uint64tos(char* output, uint64_t i, unsigned i_len) { 122 static void my_uint64tos(char* output, uint64_t i, unsigned i_len) {
113 for (unsigned index = i_len; index; --index, i /= 10) 123 for (unsigned index = i_len; index; --index, i /= 10)
114 output[index - 1] = '0' + (i % 10); 124 output[index - 1] = '0' + (i % 10);
115 } 125 }
116 126
127 static inline char*
128 my_strncpy(char* dst, const char* src, size_t len) {
129 int i = len;
130 char* p = dst;
131 if (!dst || !src)
132 return dst;
133 while (i != 0 && *src != '\0') {
134 *p++ = *src++;
135 i--;
136 }
137 while (i != 0) {
138 *p++ = '\0';
139 i--;
140 }
141 return dst;
142 }
143
144 static inline char*
145 my_strncat(char *dest, const char *src, size_t len) {
146 char *ret = dest;
147 while (*dest)
148 dest++;
149 while (len--)
150 if (!(*dest++ = *src++))
151 return ret;
152 *dest = 0;
153 return ret;
154 }
155
117 namespace { 156 namespace {
118 157
119 // MIME substrings. 158 // MIME substrings.
120 static const char g_rn[] = "\r\n"; 159 static const char g_rn[] = "\r\n";
121 static const char g_form_data_msg[] = "Content-Disposition: form-data; name=\""; 160 static const char g_form_data_msg[] = "Content-Disposition: form-data; name=\"";
122 static const char g_quote_msg[] = "\""; 161 static const char g_quote_msg[] = "\"";
123 static const char g_dashdash_msg[] = "--"; 162 static const char g_dashdash_msg[] = "--";
124 static const char g_dump_msg[] = "upload_file_minidump\"; filename=\"dump\""; 163 static const char g_dump_msg[] = "upload_file_minidump\"; filename=\"dump\"";
125 static const char g_content_type_msg[] = 164 static const char g_content_type_msg[] =
126 "Content-Type: application/octet-stream"; 165 "Content-Type: application/octet-stream";
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 AddItem(base, size); 335 AddItem(base, size);
297 } 336 }
298 337
299 void DumpProcess() { 338 void DumpProcess() {
300 if (g_breakpad) 339 if (g_breakpad)
301 g_breakpad->WriteMinidump(); 340 g_breakpad->WriteMinidump();
302 } 341 }
303 342
304 } // namespace 343 } // namespace
305 344
345 void log(const char* buf, size_t nbytes) {
346 #if defined(__ANDROID__)
347 return __android_log_write(ANDROID_LOG_WARN, "google-breakpad", buf);
348 #else
349 return sys_write(2, buf, nbytes)
350 #endif
351 }
352
306 void HandleCrashDump(const BreakpadInfo& info) { 353 void HandleCrashDump(const BreakpadInfo& info) {
307 // WARNING: this code runs in a compromised context. It may not call into 354 // WARNING: this code runs in a compromised context. It may not call into
308 // libc nor allocate memory normally. 355 // libc nor allocate memory normally.
309 356
310 const int dumpfd = sys_open(info.filename, O_RDONLY, 0); 357 const int dumpfd = sys_open(info.filename, O_RDONLY, 0);
311 if (dumpfd < 0) { 358 if (dumpfd < 0) {
312 static const char msg[] = "Cannot upload crash dump: failed to open\n"; 359 static const char msg[] = "Cannot upload crash dump: failed to open\n";
313 sys_write(2, msg, sizeof(msg)); 360 log(msg, sizeof(msg));
314 return; 361 return;
315 } 362 }
316 struct kernel_stat st; 363 struct kernel_stat st;
317 if (sys_fstat(dumpfd, &st) != 0) { 364 if (sys_fstat(dumpfd, &st) != 0) {
318 static const char msg[] = "Cannot upload crash dump: stat failed\n"; 365 static const char msg[] = "Cannot upload crash dump: stat failed\n";
319 sys_write(2, msg, sizeof(msg)); 366 log(msg, sizeof(msg));
320 IGNORE_RET(sys_close(dumpfd)); 367 IGNORE_RET(sys_close(dumpfd));
321 return; 368 return;
322 } 369 }
323 370
324 google_breakpad::PageAllocator allocator; 371 google_breakpad::PageAllocator allocator;
325 372
326 uint8_t* dump_data = reinterpret_cast<uint8_t*>(allocator.Alloc(st.st_size)); 373 uint8_t* dump_data = reinterpret_cast<uint8_t*>(allocator.Alloc(st.st_size));
327 if (!dump_data) { 374 if (!dump_data) {
328 static const char msg[] = "Cannot upload crash dump: cannot alloc\n"; 375 static const char msg[] = "Cannot upload crash dump: cannot alloc\n";
329 sys_write(2, msg, sizeof(msg)); 376 log(msg, sizeof(msg));
330 IGNORE_RET(sys_close(dumpfd)); 377 IGNORE_RET(sys_close(dumpfd));
331 return; 378 return;
332 } 379 }
333 380
334 sys_read(dumpfd, dump_data, st.st_size); 381 sys_read(dumpfd, dump_data, st.st_size);
335 IGNORE_RET(sys_close(dumpfd)); 382 IGNORE_RET(sys_close(dumpfd));
336 383
337 // We need to build a MIME block for uploading to the server. Since we are 384 // We need to build a MIME block for uploading to the server. Since we are
338 // going to fork and run wget, it needs to be written to a temp file. 385 // going to fork and run wget, it needs to be written to a temp file.
339 386
340 const int ufd = sys_open("/dev/urandom", O_RDONLY, 0); 387 const int ufd = sys_open("/dev/urandom", O_RDONLY, 0);
341 if (ufd < 0) { 388 if (ufd < 0) {
342 static const char msg[] = "Cannot upload crash dump because /dev/urandom" 389 static const char msg[] = "Cannot upload crash dump because /dev/urandom"
343 " is missing\n"; 390 " is missing\n";
344 sys_write(2, msg, sizeof(msg) - 1); 391 log(msg, sizeof(msg) - 1);
345 return; 392 return;
346 } 393 }
347 394
348 static const char temp_file_template[] = 395 static const char temp_file_template[] =
349 "/tmp/chromium-upload-XXXXXXXXXXXXXXXX"; 396 "/tmp/chromium-upload-XXXXXXXXXXXXXXXX";
350 char temp_file[sizeof(temp_file_template)]; 397 char temp_file[sizeof(temp_file_template)];
351 int temp_file_fd = -1; 398 int temp_file_fd = -1;
352 if (info.upload) { 399 if (info.upload) {
353 memcpy(temp_file, temp_file_template, sizeof(temp_file_template)); 400 memcpy(temp_file, temp_file_template, sizeof(temp_file_template));
354 401
355 for (unsigned i = 0; i < 10; ++i) { 402 for (unsigned i = 0; i < 10; ++i) {
356 uint64_t t; 403 uint64_t t;
357 sys_read(ufd, &t, sizeof(t)); 404 sys_read(ufd, &t, sizeof(t));
358 write_uint64_hex(temp_file + sizeof(temp_file) - (16 + 1), t); 405 write_uint64_hex(temp_file + sizeof(temp_file) - (16 + 1), t);
359 406
360 temp_file_fd = sys_open(temp_file, O_WRONLY | O_CREAT | O_EXCL, 0600); 407 temp_file_fd = sys_open(temp_file, O_WRONLY | O_CREAT | O_EXCL, 0600);
361 if (temp_file_fd >= 0) 408 if (temp_file_fd >= 0)
362 break; 409 break;
363 } 410 }
364 411
365 if (temp_file_fd < 0) { 412 if (temp_file_fd < 0) {
366 static const char msg[] = "Failed to create temporary file in /tmp: " 413 static const char msg[] = "Failed to create temporary file in /tmp: "
367 "cannot upload crash dump\n"; 414 "cannot upload crash dump\n";
368 sys_write(2, msg, sizeof(msg) - 1); 415 log(msg, sizeof(msg) - 1);
369 IGNORE_RET(sys_close(ufd)); 416 IGNORE_RET(sys_close(ufd));
370 return; 417 return;
371 } 418 }
372 } else { 419 } else {
373 temp_file_fd = sys_open(info.filename, O_WRONLY, 0600); 420 temp_file_fd = sys_open(info.filename, O_WRONLY, 0600);
374 if (temp_file_fd < 0) { 421 if (temp_file_fd < 0) {
375 static const char msg[] = "Failed to save crash dump: failed to open\n"; 422 static const char msg[] = "Failed to save crash dump: failed to open\n";
376 sys_write(2, msg, sizeof(msg) - 1); 423 log(msg, sizeof(msg) - 1);
377 IGNORE_RET(sys_close(ufd)); 424 IGNORE_RET(sys_close(ufd));
378 return; 425 return;
379 } 426 }
380 } 427 }
381 428
382 // The MIME boundary is 28 hyphens, followed by a 64-bit nonce and a NUL. 429 // The MIME boundary is 28 hyphens, followed by a 64-bit nonce and a NUL.
383 char mime_boundary[28 + 16 + 1]; 430 char mime_boundary[28 + 16 + 1];
384 my_memset(mime_boundary, '-', 28); 431 my_memset(mime_boundary, '-', 28);
385 uint64_t boundary_rand; 432 uint64_t boundary_rand;
386 sys_read(ufd, &boundary_rand, sizeof(boundary_rand)); 433 sys_read(ufd, &boundary_rand, sizeof(boundary_rand));
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 // --foo \r\n 502 // --foo \r\n
456 // BOUNDARY \r\n 503 // BOUNDARY \r\n
457 // 504 //
458 // Content-Disposition: form-data; name="dump"; filename="dump" \r\n 505 // Content-Disposition: form-data; name="dump"; filename="dump" \r\n
459 // Content-Type: application/octet-stream \r\n \r\n 506 // Content-Type: application/octet-stream \r\n \r\n
460 // <dump contents> 507 // <dump contents>
461 // \r\n BOUNDARY -- \r\n 508 // \r\n BOUNDARY -- \r\n
462 509
463 MimeWriter writer(temp_file_fd, mime_boundary); 510 MimeWriter writer(temp_file_fd, mime_boundary);
464 { 511 {
465 #if defined(OS_CHROMEOS) 512 #if defined(OS_ANDROID)
513 static const char chrome_product_msg[] = "Chrome_Android";
514 #elif defined(OS_CHROMEOS)
466 static const char chrome_product_msg[] = "Chrome_ChromeOS"; 515 static const char chrome_product_msg[] = "Chrome_ChromeOS";
467 #else // OS_LINUX 516 #else // OS_LINUX
468 static const char chrome_product_msg[] = "Chrome_Linux"; 517 static const char chrome_product_msg[] = "Chrome_Linux";
469 #endif 518 #endif
519
520 #if defined (OS_ANDROID)
521 const base::android::BuildInfo* android_build_info =
522 base::android::BuildInfo::GetInstance();
523 static const char* version_msg = android_build_info->package_version_code;
524 static const char android_build_id[] = "android_build_id";
525 static const char android_build_fp[] = "android_build_fp";
526 static const char device[] = "device";
527 static const char model[] = "model";
528 static const char brand[] = "brand";
529 #else
470 static const char version_msg[] = PRODUCT_VERSION; 530 static const char version_msg[] = PRODUCT_VERSION;
531 #endif
471 532
472 writer.AddBoundary(); 533 writer.AddBoundary();
473 writer.AddPairString("prod", chrome_product_msg); 534 writer.AddPairString("prod", chrome_product_msg);
474 writer.AddBoundary(); 535 writer.AddBoundary();
475 writer.AddPairString("ver", version_msg); 536 writer.AddPairString("ver", version_msg);
476 writer.AddBoundary(); 537 writer.AddBoundary();
477 writer.AddPairString("guid", info.guid); 538 writer.AddPairString("guid", info.guid);
478 writer.AddBoundary(); 539 writer.AddBoundary();
540 if (info.pid > -1) {
541 uint64_t pid_str_len = my_uint64_len(info.pid);
542 char* pid_buf = reinterpret_cast<char*>(alllocator.Alloc(pid_str_len));
543 my_uint64tos(pid_buf, info.pid, pid_str_len);
544 writer.AddPairString("pid", pid_buf);
545 writer.AddBoundary();
546 }
547 #if defined(OS_ANDROID)
548 // Addtional MIME blocks are added for logging on Android devices.
549 writer.AddPairString(
550 android_build_id, android_build_info->android_build_id);
551 writer.AddBoundary();
552 writer.AddPairString(
553 android_build_fp, android_build_info->android_build_fp);
554 writer.AddBoundary();
555 writer.AddPairString(device, android_build_info->device);
556 writer.AddBoundary();
557 writer.AddPairString(model, android_build_info->model);
558 writer.AddBoundary();
559 writer.AddPairString(brand, android_build_info->brand);
560 writer.AddBoundary();
561 #endif
479 writer.Flush(); 562 writer.Flush();
480 } 563 }
481 564
482 if (info.process_start_time > 0) { 565 if (info.process_start_time > 0) {
483 struct kernel_timeval tv; 566 struct kernel_timeval tv;
484 if (!sys_gettimeofday(&tv, NULL)) { 567 if (!sys_gettimeofday(&tv, NULL)) {
485 uint64_t time = kernel_timeval_to_ms(&tv); 568 uint64_t time = kernel_timeval_to_ms(&tv);
486 if (time > info.process_start_time) { 569 if (time > info.process_start_time) {
487 time -= info.process_start_time; 570 time -= info.process_start_time;
488 char time_str[21]; 571 char time_str[21];
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 std::min(switches_len, kMaxSwitchLen), 688 std::min(switches_len, kMaxSwitchLen),
606 child_process_logging::kSwitchLen, 689 child_process_logging::kSwitchLen,
607 true /* Strip whitespace since switches are padded to kSwitchLen. */); 690 true /* Strip whitespace since switches are padded to kSwitchLen. */);
608 } 691 }
609 692
610 writer.AddFileDump(dump_data, st.st_size); 693 writer.AddFileDump(dump_data, st.st_size);
611 writer.AddEnd(); 694 writer.AddEnd();
612 writer.Flush(); 695 writer.Flush();
613 696
614 IGNORE_RET(sys_close(temp_file_fd)); 697 IGNORE_RET(sys_close(temp_file_fd));
698 #if defined(OS_ANDROID)
699 const char* output_msg = "Output crash dump file:";
700 __android_log_write(ANDROID_LOG_WARN, "chromium", output_msg);
Yaron 2012/03/26 18:51:15 Why are these printed with "chromium" whereas the
carlosvaldivia 2012/04/03 06:24:47 breakpad_posix is chromium code. The other cl is g
701 __android_log_write(ANDROID_LOG_WARN, "chromium", info.filename);
702 // -1 because we won't need the null terminator on the original filename.
703 unsigned done_filename_len = info.filename_length -1 + info.pid_str_length;
704 char* done_filename = reinterpret_cast<char*>(
705 allocator.Alloc(done_filename_len));
706 // Rename the file such that the pid is the suffix in order signal to other
707 // processes that the minidump is complete. The advantage of using the pid as
708 // the suffix is that it is trivial to associate the minidump with the
709 // crashed process.
710 // Finally, note strncpy prevents null terminators from
711 // being copied. Pad the rest with 0's.
712 my_strncpy(done_filename, info.filename, done_filename_len);
713 // Append the suffix a null terminator should be added.
714 my_strncat(done_filename, info.pid_str, info.pid_str_length);
715 // Rename the minidump file to signal that it is complete.
716 if (rename(info.filename, done_filename)) {
717 __android_log_write(ANDROID_LOG_WARN, "chromium", "Failed to rename:");
718 __android_log_write(ANDROID_LOG_WARN, "chromium", info.filename);
719 __android_log_write(ANDROID_LOG_WARN, "chromium", "to");
720 __android_log_write(ANDROID_LOG_WARN, "chromium", done_filename);
721 }
722 #endif
615 723
616 if (!info.upload) 724 if (!info.upload)
617 return; 725 return;
618 726
619 // The --header argument to wget looks like: 727 // The --header argument to wget looks like:
620 // --header=Content-Type: multipart/form-data; boundary=XYZ 728 // --header=Content-Type: multipart/form-data; boundary=XYZ
621 // where the boundary has two fewer leading '-' chars 729 // where the boundary has two fewer leading '-' chars
622 static const char header_msg[] = 730 static const char header_msg[] =
623 "--header=Content-Type: multipart/form-data; boundary="; 731 "--header=Content-Type: multipart/form-data; boundary=";
624 char* const header = reinterpret_cast<char*>(allocator.Alloc( 732 char* const header = reinterpret_cast<char*>(allocator.Alloc(
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
686 "--timeout=10", // Set a timeout so we don't hang forever. 794 "--timeout=10", // Set a timeout so we don't hang forever.
687 "--tries=1", // Don't retry if the upload fails. 795 "--tries=1", // Don't retry if the upload fails.
688 "-O", // output reply to fd 3 796 "-O", // output reply to fd 3
689 "/dev/fd/3", 797 "/dev/fd/3",
690 NULL, 798 NULL,
691 }; 799 };
692 800
693 execve(kWgetBinary, const_cast<char**>(args), environ); 801 execve(kWgetBinary, const_cast<char**>(args), environ);
694 static const char msg[] = "Cannot upload crash dump: cannot exec " 802 static const char msg[] = "Cannot upload crash dump: cannot exec "
695 "/usr/bin/wget\n"; 803 "/usr/bin/wget\n";
696 sys_write(2, msg, sizeof(msg) - 1); 804 log(msg, sizeof(msg) - 1);
697 sys__exit(1); 805 sys__exit(1);
698 } 806 }
699 807
700 // Helper process. 808 // Helper process.
701 if (wget_child > 0) { 809 if (wget_child > 0) {
702 IGNORE_RET(sys_close(fds[1])); 810 IGNORE_RET(sys_close(fds[1]));
703 char id_buf[17]; // Crash report IDs are expected to be 16 chars. 811 char id_buf[17]; // Crash report IDs are expected to be 16 chars.
704 ssize_t len = -1; 812 ssize_t len = -1;
705 // Wget should finish in about 10 seconds. Add a few more 500 ms 813 // Wget should finish in about 10 seconds. Add a few more 500 ms
706 // internals to account for process startup time. 814 // internals to account for process startup time.
707 for (size_t wait_count = 0; wait_count < 24; ++wait_count) { 815 for (size_t wait_count = 0; wait_count < 24; ++wait_count) {
708 struct kernel_pollfd poll_fd; 816 struct kernel_pollfd poll_fd;
709 poll_fd.fd = fds[0]; 817 poll_fd.fd = fds[0];
710 poll_fd.events = POLLIN | POLLPRI | POLLERR; 818 poll_fd.events = POLLIN | POLLPRI | POLLERR;
711 int ret = sys_poll(&poll_fd, 1, 500); 819 int ret = sys_poll(&poll_fd, 1, 500);
712 if (ret < 0) { 820 if (ret < 0) {
713 // Error 821 // Error
714 break; 822 break;
715 } else if (ret > 0) { 823 } else if (ret > 0) {
716 // There is data to read. 824 // There is data to read.
717 len = HANDLE_EINTR(sys_read(fds[0], id_buf, sizeof(id_buf) - 1)); 825 len = HANDLE_EINTR(sys_read(fds[0], id_buf, sizeof(id_buf) - 1));
718 break; 826 break;
719 } 827 }
720 // ret == 0 -> timed out, continue waiting. 828 // ret == 0 -> timed out, continue waiting.
721 } 829 }
722 if (len > 0) { 830 if (len > 0) {
723 // Write crash dump id to stderr. 831 // Write crash dump id to stderr.
724 id_buf[len] = 0; 832 id_buf[len] = 0;
725 static const char msg[] = "\nCrash dump id: "; 833 static const char msg[] = "\nCrash dump id: ";
726 sys_write(2, msg, sizeof(msg) - 1); 834 log(msg, sizeof(msg) - 1);
727 sys_write(2, id_buf, my_strlen(id_buf)); 835 log(id_buf, my_strlen(id_buf));
728 sys_write(2, "\n", 1); 836 log("\n", 1);
729 837
730 // Write crash dump id to crash log as: seconds_since_epoch,crash_id 838 // Write crash dump id to crash log as: seconds_since_epoch,crash_id
731 struct kernel_timeval tv; 839 struct kernel_timeval tv;
732 if (g_crash_log_path && !sys_gettimeofday(&tv, NULL)) { 840 if (g_crash_log_path && !sys_gettimeofday(&tv, NULL)) {
733 uint64_t time = kernel_timeval_to_ms(&tv) / 1000; 841 uint64_t time = kernel_timeval_to_ms(&tv) / 1000;
734 char time_str[21]; 842 char time_str[21];
735 const unsigned time_len = my_uint64_len(time); 843 const unsigned time_len = my_uint64_len(time);
736 my_uint64tos(time_str, time, time_len); 844 my_uint64tos(time_str, time, time_len);
737 845
738 int log_fd = sys_open(g_crash_log_path, 846 int log_fd = sys_open(g_crash_log_path,
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
804 } 912 }
805 913
806 // Wrapper function, do not add more code here. 914 // Wrapper function, do not add more code here.
807 static bool CrashDoneNoUpload(const char* dump_path, 915 static bool CrashDoneNoUpload(const char* dump_path,
808 const char* minidump_id, 916 const char* minidump_id,
809 void* context, 917 void* context,
810 bool succeeded) { 918 bool succeeded) {
811 return CrashDone(dump_path, minidump_id, false, succeeded); 919 return CrashDone(dump_path, minidump_id, false, succeeded);
812 } 920 }
813 921
922 #if !defined(OS_ANDROID)
814 // Wrapper function, do not add more code here. 923 // Wrapper function, do not add more code here.
815 static bool CrashDoneUpload(const char* dump_path, 924 static bool CrashDoneUpload(const char* dump_path,
816 const char* minidump_id, 925 const char* minidump_id,
817 void* context, 926 void* context,
818 bool succeeded) { 927 bool succeeded) {
819 return CrashDone(dump_path, minidump_id, true, succeeded); 928 return CrashDone(dump_path, minidump_id, true, succeeded);
820 } 929 }
930 #endif
821 931
822 void EnableCrashDumping(const bool unattended) { 932 void EnableCrashDumping(const bool unattended) {
823 g_is_crash_reporter_enabled = true; 933 g_is_crash_reporter_enabled = true;
824 934
825 FilePath tmp_path("/tmp"); 935 FilePath tmp_path("/tmp");
826 PathService::Get(base::DIR_TEMP, &tmp_path); 936 PathService::Get(base::DIR_TEMP, &tmp_path);
827 937
828 FilePath dumps_path(tmp_path); 938 FilePath dumps_path(tmp_path);
829 if (PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path)) { 939 if (PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path)) {
830 FilePath logfile = 940 FilePath logfile =
831 dumps_path.AppendASCII(CrashUploadList::kReporterLogFilename); 941 dumps_path.AppendASCII(CrashUploadList::kReporterLogFilename);
832 std::string logfile_str = logfile.value(); 942 std::string logfile_str = logfile.value();
833 const size_t crash_log_path_len = logfile_str.size() + 1; 943 const size_t crash_log_path_len = logfile_str.size() + 1;
834 g_crash_log_path = new char[crash_log_path_len]; 944 g_crash_log_path = new char[crash_log_path_len];
835 strncpy(g_crash_log_path, logfile_str.c_str(), crash_log_path_len); 945 strncpy(g_crash_log_path, logfile_str.c_str(), crash_log_path_len);
836 } 946 }
837 947 #if defined(OS_ANDROID)
948 // In Android we never upload from native code.
949 new google_breakpad::ExceptionHandler(dumps_path.value().c_str(), NULL,
950 CrashDoneNoUpload, NULL,
951 true /* install handlers */);
952 #else
838 DCHECK(!g_breakpad); 953 DCHECK(!g_breakpad);
839 if (unattended) { 954 if (unattended) {
840 g_breakpad = new google_breakpad::ExceptionHandler( 955 g_breakpad = new google_breakpad::ExceptionHandler(
841 dumps_path.value().c_str(), 956 dumps_path.value().c_str(),
842 NULL, 957 NULL,
843 CrashDoneNoUpload, 958 CrashDoneNoUpload,
844 NULL, 959 NULL,
845 true /* install handlers */); 960 true /* install handlers */);
846 } else { 961 } else {
847 g_breakpad = new google_breakpad::ExceptionHandler( 962 g_breakpad = new google_breakpad::ExceptionHandler(
848 tmp_path.value().c_str(), 963 tmp_path.value().c_str(),
849 NULL, 964 NULL,
850 CrashDoneUpload, 965 CrashDoneUpload,
851 NULL, 966 NULL,
852 true /* install handlers */); 967 true /* install handlers */);
853 } 968 }
969 #endif
854 } 970 }
855 971
856 // Non-Browser = Extension, Gpu, Plugins, Ppapi and Renderer 972 // Non-Browser = Extension, Gpu, Plugins, Ppapi and Renderer
857 static bool NonBrowserCrashHandler(const void* crash_context, 973 static bool NonBrowserCrashHandler(const void* crash_context,
858 size_t crash_context_size, 974 size_t crash_context_size,
859 void* context) { 975 void* context) {
860 const int fd = reinterpret_cast<intptr_t>(context); 976 const int fd = reinterpret_cast<intptr_t>(context);
861 int fds[2] = { -1, -1 }; 977 int fds[2] = { -1, -1 };
862 if (sys_socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { 978 if (sys_socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
863 static const char msg[] = "Failed to create socket for crash dumping.\n"; 979 static const char msg[] = "Failed to create socket for crash dumping.\n";
864 sys_write(2, msg, sizeof(msg)-1); 980 log(msg, sizeof(msg)-1);
865 return false; 981 return false;
866 } 982 }
867 983
868 // On kernels with ptrace protection, e.g. Ubuntu 10.10+, the browser cannot 984 // On kernels with ptrace protection, e.g. Ubuntu 10.10+, the browser cannot
869 // ptrace this crashing process and crash dumping will fail. When using the 985 // ptrace this crashing process and crash dumping will fail. When using the
870 // SUID sandbox, this crashing process is likely to be in its own PID 986 // SUID sandbox, this crashing process is likely to be in its own PID
871 // namespace, and thus there is no way to permit only the browser process to 987 // namespace, and thus there is no way to permit only the browser process to
872 // ptrace it. 988 // ptrace it.
873 // The workaround is to allow all processes to ptrace this process if we 989 // The workaround is to allow all processes to ptrace this process if we
874 // reach this point, by passing -1 as the allowed PID. However, support for 990 // reach this point, by passing -1 as the allowed PID. However, support for
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
929 1045
930 struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); 1046 struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg);
931 hdr->cmsg_level = SOL_SOCKET; 1047 hdr->cmsg_level = SOL_SOCKET;
932 hdr->cmsg_type = SCM_RIGHTS; 1048 hdr->cmsg_type = SCM_RIGHTS;
933 hdr->cmsg_len = kControlMsgLenSize; 1049 hdr->cmsg_len = kControlMsgLenSize;
934 ((int*) CMSG_DATA(hdr))[0] = fds[0]; 1050 ((int*) CMSG_DATA(hdr))[0] = fds[0];
935 ((int*) CMSG_DATA(hdr))[1] = fds[1]; 1051 ((int*) CMSG_DATA(hdr))[1] = fds[1];
936 1052
937 if (HANDLE_EINTR(sys_sendmsg(fd, &msg, 0)) < 0) { 1053 if (HANDLE_EINTR(sys_sendmsg(fd, &msg, 0)) < 0) {
938 static const char errmsg[] = "Failed to tell parent about crash.\n"; 1054 static const char errmsg[] = "Failed to tell parent about crash.\n";
939 sys_write(2, errmsg, sizeof(errmsg)-1); 1055 log(errmsg, sizeof(errmsg)-1);
940 IGNORE_RET(sys_close(fds[1])); 1056 IGNORE_RET(sys_close(fds[1]));
941 return false; 1057 return false;
942 } 1058 }
943 IGNORE_RET(sys_close(fds[1])); 1059 IGNORE_RET(sys_close(fds[1]));
944 1060
945 if (HANDLE_EINTR(sys_read(fds[0], &b, 1)) != 1) { 1061 if (HANDLE_EINTR(sys_read(fds[0], &b, 1)) != 1) {
946 static const char errmsg[] = "Parent failed to complete crash dump.\n"; 1062 static const char errmsg[] = "Parent failed to complete crash dump.\n";
947 sys_write(2, errmsg, sizeof(errmsg)-1); 1063 log(errmsg, sizeof(errmsg)-1);
948 } 1064 }
949 1065
950 return true; 1066 return true;
951 } 1067 }
952 1068
953 void EnableNonBrowserCrashDumping() { 1069 void EnableNonBrowserCrashDumping() {
954 const int fd = base::GlobalDescriptors::GetInstance()->Get(kCrashDumpSignal); 1070 const int fd = base::GlobalDescriptors::GetInstance()->Get(kCrashDumpSignal);
955 g_is_crash_reporter_enabled = true; 1071 g_is_crash_reporter_enabled = true;
956 // We deliberately leak this object. 1072 // We deliberately leak this object.
957 DCHECK(!g_breakpad); 1073 DCHECK(!g_breakpad);
958 g_breakpad = new google_breakpad::ExceptionHandler( 1074 g_breakpad = new google_breakpad::ExceptionHandler(
959 "" /* unused */, NULL, NULL, reinterpret_cast<void*>(fd), true); 1075 "" /* unused */, NULL, NULL, reinterpret_cast<void*>(fd), true);
960 g_breakpad->set_crash_handler(NonBrowserCrashHandler); 1076 g_breakpad->set_crash_handler(NonBrowserCrashHandler);
961 } 1077 }
962 1078
963 void InitCrashReporter() { 1079 void InitCrashReporter() {
1080 #if defined(OS_ANDROID)
1081 // This will guarantee that the BuildInfo has been initialized and subsequent
1082 // calls will not require memory allocation.
1083 base::android::BuildInfo::GetInstance();
1084 #endif
964 // Determine the process type and take appropriate action. 1085 // Determine the process type and take appropriate action.
965 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); 1086 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
966 if (parsed_command_line.HasSwitch(switches::kDisableBreakpad)) 1087 if (parsed_command_line.HasSwitch(switches::kDisableBreakpad))
967 return; 1088 return;
968 1089
969 const std::string process_type = 1090 const std::string process_type =
970 parsed_command_line.GetSwitchValueASCII(switches::kProcessType); 1091 parsed_command_line.GetSwitchValueASCII(switches::kProcessType);
971 if (process_type.empty()) { 1092 if (process_type.empty()) {
972 EnableCrashDumping(getenv(env_vars::kHeadless) != NULL); 1093 EnableCrashDumping(getenv(env_vars::kHeadless) != NULL);
973 } else if (process_type == switches::kRendererProcess || 1094 } else if (process_type == switches::kRendererProcess ||
974 process_type == switches::kPluginProcess || 1095 process_type == switches::kPluginProcess ||
975 process_type == switches::kPpapiPluginProcess || 1096 process_type == switches::kPpapiPluginProcess ||
976 process_type == switches::kZygoteProcess || 1097 process_type == switches::kZygoteProcess ||
977 process_type == switches::kGpuProcess) { 1098 process_type == switches::kGpuProcess) {
1099 #if defined(OS_ANDROID)
1100 child_process_logging::SetClientId("Android");
1101 #endif
978 // We might be chrooted in a zygote or renderer process so we cannot call 1102 // We might be chrooted in a zygote or renderer process so we cannot call
979 // GetCollectStatsConsent because that needs access the the user's home 1103 // GetCollectStatsConsent because that needs access the the user's home
980 // dir. Instead, we set a command line flag for these processes. 1104 // dir. Instead, we set a command line flag for these processes.
981 // Even though plugins are not chrooted, we share the same code path for 1105 // Even though plugins are not chrooted, we share the same code path for
982 // simplicity. 1106 // simplicity.
983 if (!parsed_command_line.HasSwitch(switches::kEnableCrashReporter)) 1107 if (!parsed_command_line.HasSwitch(switches::kEnableCrashReporter))
984 return; 1108 return;
985 // Get the guid and linux distro from the command line switch. 1109 // Get the guid and linux distro from the command line switch.
986 std::string switch_value = 1110 std::string switch_value =
987 parsed_command_line.GetSwitchValueASCII(switches::kEnableCrashReporter); 1111 parsed_command_line.GetSwitchValueASCII(switches::kEnableCrashReporter);
(...skipping 13 matching lines...) Expand all
1001 g_process_start_time = timeval_to_ms(&tv); 1125 g_process_start_time = timeval_to_ms(&tv);
1002 else 1126 else
1003 g_process_start_time = 0; 1127 g_process_start_time = 0;
1004 1128
1005 logging::SetDumpWithoutCrashingFunction(&DumpProcess); 1129 logging::SetDumpWithoutCrashingFunction(&DumpProcess);
1006 } 1130 }
1007 1131
1008 bool IsCrashReporterEnabled() { 1132 bool IsCrashReporterEnabled() {
1009 return g_is_crash_reporter_enabled; 1133 return g_is_crash_reporter_enabled;
1010 } 1134 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698