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

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: 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 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 25 matching lines...) Expand all
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"
45 45
46 #ifdef OS_ANDROID
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 char* my_strncpy(char* dst, const char* src, size_t len) {
128 int i = len;
129 char* p = dst;
130 if (!dst || !src)
131 return dst;
132 while (i != 0 && *src != '\0') {
133 *p++ = *src++;
134 i--;
135 }
136 while (i != 0) {
137 *p++ = '\0';
138 i--;
139 }
140 return dst;
141 }
142
143 static char* my_strncat(char *dest, const char *src, size_t len) {
144 char *ret = dest;
145 while (*dest)
146 dest++;
147 while (len--)
148 if (!(*dest++ = *src++))
149 return ret;
150 *dest = 0;
151 return ret;
152 }
153
117 namespace { 154 namespace {
118 155
119 // MIME substrings. 156 // MIME substrings.
120 static const char g_rn[] = "\r\n"; 157 static const char g_rn[] = "\r\n";
121 static const char g_form_data_msg[] = "Content-Disposition: form-data; name=\""; 158 static const char g_form_data_msg[] = "Content-Disposition: form-data; name=\"";
122 static const char g_quote_msg[] = "\""; 159 static const char g_quote_msg[] = "\"";
123 static const char g_dashdash_msg[] = "--"; 160 static const char g_dashdash_msg[] = "--";
124 static const char g_dump_msg[] = "upload_file_minidump\"; filename=\"dump\""; 161 static const char g_dump_msg[] = "upload_file_minidump\"; filename=\"dump\"";
125 static const char g_content_type_msg[] = 162 static const char g_content_type_msg[] =
126 "Content-Type: application/octet-stream"; 163 "Content-Type: application/octet-stream";
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 size--; 331 size--;
295 } 332 }
296 AddItem(base, size); 333 AddItem(base, size);
297 } 334 }
298 335
299 void DumpProcess() { 336 void DumpProcess() {
300 if (g_breakpad) 337 if (g_breakpad)
301 g_breakpad->WriteMinidump(); 338 g_breakpad->WriteMinidump();
302 } 339 }
303 340
341 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
342 #if defined(OS_ANDROID)
343 return __android_log_write(ANDROID_LOG_WARN, "google-breakpad", buf);
344 #else
345 return sys_write(2, buf, nbytes)
346 #endif
347 }
348
304 } // namespace 349 } // namespace
305 350
351 void log(const char* buf, size_t nbytes) {
352 #if defined(OS_ANDROID)
353 return __android_log_write(ANDROID_LOG_WARN, "google-breakpad", buf);
354 #else
355 return sys_write(2, buf, nbytes)
356 #endif
357 }
358
306 void HandleCrashDump(const BreakpadInfo& info) { 359 void HandleCrashDump(const BreakpadInfo& info) {
307 // WARNING: this code runs in a compromised context. It may not call into 360 // WARNING: this code runs in a compromised context. It may not call into
308 // libc nor allocate memory normally. 361 // libc nor allocate memory normally.
309 362
310 const int dumpfd = sys_open(info.filename, O_RDONLY, 0); 363 const int dumpfd = sys_open(info.filename, O_RDONLY, 0);
311 if (dumpfd < 0) { 364 if (dumpfd < 0) {
312 static const char msg[] = "Cannot upload crash dump: failed to open\n"; 365 static const char msg[] = "Cannot upload crash dump: failed to open\n";
313 sys_write(2, msg, sizeof(msg)); 366 log(msg, sizeof(msg));
314 return; 367 return;
315 } 368 }
369 #if defined(OS_ANDROID)
370 struct stat st;
371 if (fstat(dumpfd, &st) != 0) {
372 #else
316 struct kernel_stat st; 373 struct kernel_stat st;
317 if (sys_fstat(dumpfd, &st) != 0) { 374 if (sys_fstat(dumpfd, &st) != 0) {
375 #endif
318 static const char msg[] = "Cannot upload crash dump: stat failed\n"; 376 static const char msg[] = "Cannot upload crash dump: stat failed\n";
319 sys_write(2, msg, sizeof(msg)); 377 log(msg, sizeof(msg));
320 IGNORE_RET(sys_close(dumpfd)); 378 IGNORE_RET(sys_close(dumpfd));
321 return; 379 return;
322 } 380 }
323 381
324 google_breakpad::PageAllocator allocator; 382 google_breakpad::PageAllocator allocator;
325 383
326 uint8_t* dump_data = reinterpret_cast<uint8_t*>(allocator.Alloc(st.st_size)); 384 uint8_t* dump_data = reinterpret_cast<uint8_t*>(allocator.Alloc(st.st_size));
327 if (!dump_data) { 385 if (!dump_data) {
328 static const char msg[] = "Cannot upload crash dump: cannot alloc\n"; 386 static const char msg[] = "Cannot upload crash dump: cannot alloc\n";
329 sys_write(2, msg, sizeof(msg)); 387 log(msg, sizeof(msg));
330 IGNORE_RET(sys_close(dumpfd)); 388 IGNORE_RET(sys_close(dumpfd));
331 return; 389 return;
332 } 390 }
333 391
334 sys_read(dumpfd, dump_data, st.st_size); 392 sys_read(dumpfd, dump_data, st.st_size);
335 IGNORE_RET(sys_close(dumpfd)); 393 IGNORE_RET(sys_close(dumpfd));
336 394
337 // We need to build a MIME block for uploading to the server. Since we are 395 // 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. 396 // going to fork and run wget, it needs to be written to a temp file.
339 397
340 const int ufd = sys_open("/dev/urandom", O_RDONLY, 0); 398 const int ufd = sys_open("/dev/urandom", O_RDONLY, 0);
341 if (ufd < 0) { 399 if (ufd < 0) {
342 static const char msg[] = "Cannot upload crash dump because /dev/urandom" 400 static const char msg[] = "Cannot upload crash dump because /dev/urandom"
343 " is missing\n"; 401 " is missing\n";
344 sys_write(2, msg, sizeof(msg) - 1); 402 log(msg, sizeof(msg) - 1);
345 return; 403 return;
346 } 404 }
347 405
348 static const char temp_file_template[] = 406 static const char temp_file_template[] =
349 "/tmp/chromium-upload-XXXXXXXXXXXXXXXX"; 407 "/tmp/chromium-upload-XXXXXXXXXXXXXXXX";
350 char temp_file[sizeof(temp_file_template)]; 408 char temp_file[sizeof(temp_file_template)];
351 int temp_file_fd = -1; 409 int temp_file_fd = -1;
352 if (info.upload) { 410 if (info.upload) {
353 memcpy(temp_file, temp_file_template, sizeof(temp_file_template)); 411 memcpy(temp_file, temp_file_template, sizeof(temp_file_template));
354 412
355 for (unsigned i = 0; i < 10; ++i) { 413 for (unsigned i = 0; i < 10; ++i) {
356 uint64_t t; 414 uint64_t t;
357 sys_read(ufd, &t, sizeof(t)); 415 sys_read(ufd, &t, sizeof(t));
358 write_uint64_hex(temp_file + sizeof(temp_file) - (16 + 1), t); 416 write_uint64_hex(temp_file + sizeof(temp_file) - (16 + 1), t);
359 417
360 temp_file_fd = sys_open(temp_file, O_WRONLY | O_CREAT | O_EXCL, 0600); 418 temp_file_fd = sys_open(temp_file, O_WRONLY | O_CREAT | O_EXCL, 0600);
361 if (temp_file_fd >= 0) 419 if (temp_file_fd >= 0)
362 break; 420 break;
363 } 421 }
364 422
365 if (temp_file_fd < 0) { 423 if (temp_file_fd < 0) {
366 static const char msg[] = "Failed to create temporary file in /tmp: " 424 static const char msg[] = "Failed to create temporary file in /tmp: "
367 "cannot upload crash dump\n"; 425 "cannot upload crash dump\n";
368 sys_write(2, msg, sizeof(msg) - 1); 426 log(msg, sizeof(msg) - 1);
369 IGNORE_RET(sys_close(ufd)); 427 IGNORE_RET(sys_close(ufd));
370 return; 428 return;
371 } 429 }
372 } else { 430 } else {
373 temp_file_fd = sys_open(info.filename, O_WRONLY, 0600); 431 temp_file_fd = sys_open(info.filename, O_WRONLY, 0600);
374 if (temp_file_fd < 0) { 432 if (temp_file_fd < 0) {
375 static const char msg[] = "Failed to save crash dump: failed to open\n"; 433 static const char msg[] = "Failed to save crash dump: failed to open\n";
376 sys_write(2, msg, sizeof(msg) - 1); 434 log(msg, sizeof(msg) - 1);
377 IGNORE_RET(sys_close(ufd)); 435 IGNORE_RET(sys_close(ufd));
378 return; 436 return;
379 } 437 }
380 } 438 }
381 439
382 // The MIME boundary is 28 hyphens, followed by a 64-bit nonce and a NUL. 440 // The MIME boundary is 28 hyphens, followed by a 64-bit nonce and a NUL.
383 char mime_boundary[28 + 16 + 1]; 441 char mime_boundary[28 + 16 + 1];
384 my_memset(mime_boundary, '-', 28); 442 my_memset(mime_boundary, '-', 28);
385 uint64_t boundary_rand; 443 uint64_t boundary_rand;
386 sys_read(ufd, &boundary_rand, sizeof(boundary_rand)); 444 sys_read(ufd, &boundary_rand, sizeof(boundary_rand));
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 // --foo \r\n 513 // --foo \r\n
456 // BOUNDARY \r\n 514 // BOUNDARY \r\n
457 // 515 //
458 // Content-Disposition: form-data; name="dump"; filename="dump" \r\n 516 // Content-Disposition: form-data; name="dump"; filename="dump" \r\n
459 // Content-Type: application/octet-stream \r\n \r\n 517 // Content-Type: application/octet-stream \r\n \r\n
460 // <dump contents> 518 // <dump contents>
461 // \r\n BOUNDARY -- \r\n 519 // \r\n BOUNDARY -- \r\n
462 520
463 MimeWriter writer(temp_file_fd, mime_boundary); 521 MimeWriter writer(temp_file_fd, mime_boundary);
464 { 522 {
465 #if defined(OS_CHROMEOS) 523 #if defined(OS_ANDROID)
524 static const char chrome_product_msg[] = "Chrome_Android";
525 #elif defined(OS_CHROMEOS)
466 static const char chrome_product_msg[] = "Chrome_ChromeOS"; 526 static const char chrome_product_msg[] = "Chrome_ChromeOS";
467 #else // OS_LINUX 527 #else // OS_LINUX
468 static const char chrome_product_msg[] = "Chrome_Linux"; 528 static const char chrome_product_msg[] = "Chrome_Linux";
469 #endif 529 #endif
530
531 #if defined (OS_ANDROID)
532 const base::android::BuildInfo* android_build_info =
533 base::android::BuildInfo::GetInstance();
534 static const char* version_msg = android_build_info->package_version_code;
535 static const char android_build_id[] = "android_build_id";
536 static const char android_build_fp[] = "android_build_fp";
537 static const char device[] = "device";
538 static const char model[] = "model";
539 static const char brand[] = "brand";
540 #else
470 static const char version_msg[] = PRODUCT_VERSION; 541 static const char version_msg[] = PRODUCT_VERSION;
542 #endif
471 543
472 writer.AddBoundary(); 544 writer.AddBoundary();
473 writer.AddPairString("prod", chrome_product_msg); 545 writer.AddPairString("prod", chrome_product_msg);
474 writer.AddBoundary(); 546 writer.AddBoundary();
475 writer.AddPairString("ver", version_msg); 547 writer.AddPairString("ver", version_msg);
476 writer.AddBoundary(); 548 writer.AddBoundary();
477 writer.AddPairString("guid", info.guid); 549 writer.AddPairString("guid", info.guid);
478 writer.AddBoundary(); 550 writer.AddBoundary();
551 if (info.pid > 0) {
552 uint64_t pid_str_len = my_uint64_len(info.pid);
553 char* pid_buf = reinterpret_cast<char*>(allocator.Alloc(pid_str_len));
554 my_uint64tos(pid_buf, info.pid, pid_str_len);
555 writer.AddPairString("pid", pid_buf);
556 writer.AddBoundary();
557 }
558 #if defined(OS_ANDROID)
559 // Addtional MIME blocks are added for logging on Android devices.
560 writer.AddPairString(
561 android_build_id, android_build_info->android_build_id);
562 writer.AddBoundary();
563 writer.AddPairString(
564 android_build_fp, android_build_info->android_build_fp);
565 writer.AddBoundary();
566 writer.AddPairString(device, android_build_info->device);
567 writer.AddBoundary();
568 writer.AddPairString(model, android_build_info->model);
569 writer.AddBoundary();
570 writer.AddPairString(brand, android_build_info->brand);
571 writer.AddBoundary();
572 #endif
479 writer.Flush(); 573 writer.Flush();
480 } 574 }
481 575
482 if (info.process_start_time > 0) { 576 if (info.process_start_time > 0) {
483 struct kernel_timeval tv; 577 struct kernel_timeval tv;
484 if (!sys_gettimeofday(&tv, NULL)) { 578 if (!sys_gettimeofday(&tv, NULL)) {
485 uint64_t time = kernel_timeval_to_ms(&tv); 579 uint64_t time = kernel_timeval_to_ms(&tv);
486 if (time > info.process_start_time) { 580 if (time > info.process_start_time) {
487 time -= info.process_start_time; 581 time -= info.process_start_time;
488 char time_str[21]; 582 char time_str[21];
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
605 std::min(switches_len, kMaxSwitchLen), 699 std::min(switches_len, kMaxSwitchLen),
606 child_process_logging::kSwitchLen, 700 child_process_logging::kSwitchLen,
607 true /* Strip whitespace since switches are padded to kSwitchLen. */); 701 true /* Strip whitespace since switches are padded to kSwitchLen. */);
608 } 702 }
609 703
610 writer.AddFileDump(dump_data, st.st_size); 704 writer.AddFileDump(dump_data, st.st_size);
611 writer.AddEnd(); 705 writer.AddEnd();
612 writer.Flush(); 706 writer.Flush();
613 707
614 IGNORE_RET(sys_close(temp_file_fd)); 708 IGNORE_RET(sys_close(temp_file_fd));
709 #if defined(OS_ANDROID)
710 uint64_t pid_str_len = my_uint64_len(info.pid);
711 char* pid_buf = reinterpret_cast<char*>(allocator.Alloc(pid_str_len));
712 my_uint64tos(pid_buf, info.pid, pid_str_len);
713
714 static const char* output_msg = "Output crash dump file:";
715 log(output_msg, my_strlen(output_msg));
716 log(info.filename, info.filename_length);
717 // -1 because we won't need the null terminator on the original filename.
718 size_t done_filename_len = info.filename_length -1 + pid_str_len;
719 char* done_filename = reinterpret_cast<char*>(
720 allocator.Alloc(done_filename_len));
721 // Rename the file such that the pid is the suffix in order signal to other
722 // processes that the minidump is complete. The advantage of using the pid as
723 // the suffix is that it is trivial to associate the minidump with the
724 // crashed process.
725 // Finally, note strncpy prevents null terminators from
726 // being copied. Pad the rest with 0's.
727 my_strncpy(done_filename, info.filename, done_filename_len);
728 // Append the suffix a null terminator should be added.
729 my_strncat(done_filename, pid_buf, pid_str_len);
730 // Rename the minidump file to signal that it is complete.
731 if (rename(info.filename, done_filename)) {
732 __android_log_write(ANDROID_LOG_WARN, "chromium", "Failed to rename:");
733 __android_log_write(ANDROID_LOG_WARN, "chromium", info.filename);
734 __android_log_write(ANDROID_LOG_WARN, "chromium", "to");
735 __android_log_write(ANDROID_LOG_WARN, "chromium", done_filename);
736 }
737 #endif
615 738
616 if (!info.upload) 739 if (!info.upload)
617 return; 740 return;
618 741
619 // The --header argument to wget looks like: 742 // The --header argument to wget looks like:
620 // --header=Content-Type: multipart/form-data; boundary=XYZ 743 // --header=Content-Type: multipart/form-data; boundary=XYZ
621 // where the boundary has two fewer leading '-' chars 744 // where the boundary has two fewer leading '-' chars
622 static const char header_msg[] = 745 static const char header_msg[] =
623 "--header=Content-Type: multipart/form-data; boundary="; 746 "--header=Content-Type: multipart/form-data; boundary=";
624 char* const header = reinterpret_cast<char*>(allocator.Alloc( 747 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. 809 "--timeout=10", // Set a timeout so we don't hang forever.
687 "--tries=1", // Don't retry if the upload fails. 810 "--tries=1", // Don't retry if the upload fails.
688 "-O", // output reply to fd 3 811 "-O", // output reply to fd 3
689 "/dev/fd/3", 812 "/dev/fd/3",
690 NULL, 813 NULL,
691 }; 814 };
692 815
693 execve(kWgetBinary, const_cast<char**>(args), environ); 816 execve(kWgetBinary, const_cast<char**>(args), environ);
694 static const char msg[] = "Cannot upload crash dump: cannot exec " 817 static const char msg[] = "Cannot upload crash dump: cannot exec "
695 "/usr/bin/wget\n"; 818 "/usr/bin/wget\n";
696 sys_write(2, msg, sizeof(msg) - 1); 819 log(msg, sizeof(msg) - 1);
697 sys__exit(1); 820 sys__exit(1);
698 } 821 }
699 822
700 // Helper process. 823 // Helper process.
701 if (wget_child > 0) { 824 if (wget_child > 0) {
702 IGNORE_RET(sys_close(fds[1])); 825 IGNORE_RET(sys_close(fds[1]));
703 char id_buf[17]; // Crash report IDs are expected to be 16 chars. 826 char id_buf[17]; // Crash report IDs are expected to be 16 chars.
704 ssize_t len = -1; 827 ssize_t len = -1;
705 // Wget should finish in about 10 seconds. Add a few more 500 ms 828 // Wget should finish in about 10 seconds. Add a few more 500 ms
706 // internals to account for process startup time. 829 // internals to account for process startup time.
707 for (size_t wait_count = 0; wait_count < 24; ++wait_count) { 830 for (size_t wait_count = 0; wait_count < 24; ++wait_count) {
708 struct kernel_pollfd poll_fd; 831 struct kernel_pollfd poll_fd;
709 poll_fd.fd = fds[0]; 832 poll_fd.fd = fds[0];
710 poll_fd.events = POLLIN | POLLPRI | POLLERR; 833 poll_fd.events = POLLIN | POLLPRI | POLLERR;
711 int ret = sys_poll(&poll_fd, 1, 500); 834 int ret = sys_poll(&poll_fd, 1, 500);
712 if (ret < 0) { 835 if (ret < 0) {
713 // Error 836 // Error
714 break; 837 break;
715 } else if (ret > 0) { 838 } else if (ret > 0) {
716 // There is data to read. 839 // There is data to read.
717 len = HANDLE_EINTR(sys_read(fds[0], id_buf, sizeof(id_buf) - 1)); 840 len = HANDLE_EINTR(sys_read(fds[0], id_buf, sizeof(id_buf) - 1));
718 break; 841 break;
719 } 842 }
720 // ret == 0 -> timed out, continue waiting. 843 // ret == 0 -> timed out, continue waiting.
721 } 844 }
722 if (len > 0) { 845 if (len > 0) {
723 // Write crash dump id to stderr. 846 // Write crash dump id to stderr.
724 id_buf[len] = 0; 847 id_buf[len] = 0;
725 static const char msg[] = "\nCrash dump id: "; 848 static const char msg[] = "\nCrash dump id: ";
726 sys_write(2, msg, sizeof(msg) - 1); 849 log(msg, sizeof(msg) - 1);
727 sys_write(2, id_buf, my_strlen(id_buf)); 850 log(id_buf, my_strlen(id_buf));
728 sys_write(2, "\n", 1); 851 log("\n", 1);
729 852
730 // Write crash dump id to crash log as: seconds_since_epoch,crash_id 853 // Write crash dump id to crash log as: seconds_since_epoch,crash_id
731 struct kernel_timeval tv; 854 struct kernel_timeval tv;
732 if (g_crash_log_path && !sys_gettimeofday(&tv, NULL)) { 855 if (g_crash_log_path && !sys_gettimeofday(&tv, NULL)) {
733 uint64_t time = kernel_timeval_to_ms(&tv) / 1000; 856 uint64_t time = kernel_timeval_to_ms(&tv) / 1000;
734 char time_str[21]; 857 char time_str[21];
735 const unsigned time_len = my_uint64_len(time); 858 const unsigned time_len = my_uint64_len(time);
736 my_uint64tos(time_str, time, time_len); 859 my_uint64tos(time_str, time, time_len);
737 860
738 int log_fd = sys_open(g_crash_log_path, 861 int log_fd = sys_open(g_crash_log_path,
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
792 info.process_type = "browser"; 915 info.process_type = "browser";
793 info.process_type_length = 7; 916 info.process_type_length = 7;
794 info.crash_url = NULL; 917 info.crash_url = NULL;
795 info.crash_url_length = 0; 918 info.crash_url_length = 0;
796 info.guid = child_process_logging::g_client_id; 919 info.guid = child_process_logging::g_client_id;
797 info.guid_length = my_strlen(child_process_logging::g_client_id); 920 info.guid_length = my_strlen(child_process_logging::g_client_id);
798 info.distro = base::g_linux_distro; 921 info.distro = base::g_linux_distro;
799 info.distro_length = my_strlen(base::g_linux_distro); 922 info.distro_length = my_strlen(base::g_linux_distro);
800 info.upload = upload; 923 info.upload = upload;
801 info.process_start_time = g_process_start_time; 924 info.process_start_time = g_process_start_time;
925 info.pid = 0;
802 HandleCrashDump(info); 926 HandleCrashDump(info);
803 return true; 927 return true;
804 } 928 }
805 929
806 // Wrapper function, do not add more code here. 930 // Wrapper function, do not add more code here.
807 static bool CrashDoneNoUpload(const char* dump_path, 931 static bool CrashDoneNoUpload(const char* dump_path,
808 const char* minidump_id, 932 const char* minidump_id,
809 void* context, 933 void* context,
810 bool succeeded) { 934 bool succeeded) {
811 return CrashDone(dump_path, minidump_id, false, succeeded); 935 return CrashDone(dump_path, minidump_id, false, succeeded);
812 } 936 }
813 937
938 #if !defined(OS_ANDROID)
814 // Wrapper function, do not add more code here. 939 // Wrapper function, do not add more code here.
815 static bool CrashDoneUpload(const char* dump_path, 940 static bool CrashDoneUpload(const char* dump_path,
816 const char* minidump_id, 941 const char* minidump_id,
817 void* context, 942 void* context,
818 bool succeeded) { 943 bool succeeded) {
819 return CrashDone(dump_path, minidump_id, true, succeeded); 944 return CrashDone(dump_path, minidump_id, true, succeeded);
820 } 945 }
946 #endif
821 947
822 void EnableCrashDumping(const bool unattended) { 948 void EnableCrashDumping(const bool unattended) {
823 g_is_crash_reporter_enabled = true; 949 g_is_crash_reporter_enabled = true;
824 950
825 FilePath tmp_path("/tmp"); 951 FilePath tmp_path("/tmp");
826 PathService::Get(base::DIR_TEMP, &tmp_path); 952 PathService::Get(base::DIR_TEMP, &tmp_path);
827 953
828 FilePath dumps_path(tmp_path); 954 FilePath dumps_path(tmp_path);
829 if (PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path)) { 955 if (PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path)) {
830 FilePath logfile = 956 FilePath logfile =
831 dumps_path.AppendASCII(CrashUploadList::kReporterLogFilename); 957 dumps_path.AppendASCII(CrashUploadList::kReporterLogFilename);
832 std::string logfile_str = logfile.value(); 958 std::string logfile_str = logfile.value();
833 const size_t crash_log_path_len = logfile_str.size() + 1; 959 const size_t crash_log_path_len = logfile_str.size() + 1;
834 g_crash_log_path = new char[crash_log_path_len]; 960 g_crash_log_path = new char[crash_log_path_len];
835 strncpy(g_crash_log_path, logfile_str.c_str(), crash_log_path_len); 961 strncpy(g_crash_log_path, logfile_str.c_str(), crash_log_path_len);
836 } 962 }
837 963 #if defined(OS_ANDROID)
964 // In Android we never upload from native code.
965 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.
966 CrashDoneNoUpload, NULL,
967 true /* install handlers */);
968 #else
838 DCHECK(!g_breakpad); 969 DCHECK(!g_breakpad);
839 if (unattended) { 970 if (unattended) {
840 g_breakpad = new google_breakpad::ExceptionHandler( 971 g_breakpad = new google_breakpad::ExceptionHandler(
841 dumps_path.value().c_str(), 972 dumps_path.value().c_str(),
842 NULL, 973 NULL,
843 CrashDoneNoUpload, 974 CrashDoneNoUpload,
844 NULL, 975 NULL,
845 true /* install handlers */); 976 true /* install handlers */);
846 } else { 977 } else {
847 g_breakpad = new google_breakpad::ExceptionHandler( 978 g_breakpad = new google_breakpad::ExceptionHandler(
848 tmp_path.value().c_str(), 979 tmp_path.value().c_str(),
849 NULL, 980 NULL,
850 CrashDoneUpload, 981 CrashDoneUpload,
851 NULL, 982 NULL,
852 true /* install handlers */); 983 true /* install handlers */);
853 } 984 }
985 #endif
854 } 986 }
855 987
856 // Non-Browser = Extension, Gpu, Plugins, Ppapi and Renderer 988 // Non-Browser = Extension, Gpu, Plugins, Ppapi and Renderer
857 static bool NonBrowserCrashHandler(const void* crash_context, 989 static bool NonBrowserCrashHandler(const void* crash_context,
858 size_t crash_context_size, 990 size_t crash_context_size,
859 void* context) { 991 void* context) {
860 const int fd = reinterpret_cast<intptr_t>(context); 992 const int fd = reinterpret_cast<intptr_t>(context);
861 int fds[2] = { -1, -1 }; 993 int fds[2] = { -1, -1 };
862 if (sys_socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { 994 if (sys_socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
863 static const char msg[] = "Failed to create socket for crash dumping.\n"; 995 static const char msg[] = "Failed to create socket for crash dumping.\n";
864 sys_write(2, msg, sizeof(msg)-1); 996 log(msg, sizeof(msg)-1);
865 return false; 997 return false;
866 } 998 }
867 999
868 // On kernels with ptrace protection, e.g. Ubuntu 10.10+, the browser cannot 1000 // 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 1001 // 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 1002 // 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 1003 // namespace, and thus there is no way to permit only the browser process to
872 // ptrace it. 1004 // ptrace it.
873 // The workaround is to allow all processes to ptrace this process if we 1005 // 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 1006 // 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 1061
930 struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); 1062 struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg);
931 hdr->cmsg_level = SOL_SOCKET; 1063 hdr->cmsg_level = SOL_SOCKET;
932 hdr->cmsg_type = SCM_RIGHTS; 1064 hdr->cmsg_type = SCM_RIGHTS;
933 hdr->cmsg_len = kControlMsgLenSize; 1065 hdr->cmsg_len = kControlMsgLenSize;
934 ((int*) CMSG_DATA(hdr))[0] = fds[0]; 1066 ((int*) CMSG_DATA(hdr))[0] = fds[0];
935 ((int*) CMSG_DATA(hdr))[1] = fds[1]; 1067 ((int*) CMSG_DATA(hdr))[1] = fds[1];
936 1068
937 if (HANDLE_EINTR(sys_sendmsg(fd, &msg, 0)) < 0) { 1069 if (HANDLE_EINTR(sys_sendmsg(fd, &msg, 0)) < 0) {
938 static const char errmsg[] = "Failed to tell parent about crash.\n"; 1070 static const char errmsg[] = "Failed to tell parent about crash.\n";
939 sys_write(2, errmsg, sizeof(errmsg)-1); 1071 log(errmsg, sizeof(errmsg)-1);
940 IGNORE_RET(sys_close(fds[1])); 1072 IGNORE_RET(sys_close(fds[1]));
941 return false; 1073 return false;
942 } 1074 }
943 IGNORE_RET(sys_close(fds[1])); 1075 IGNORE_RET(sys_close(fds[1]));
944 1076
945 if (HANDLE_EINTR(sys_read(fds[0], &b, 1)) != 1) { 1077 if (HANDLE_EINTR(sys_read(fds[0], &b, 1)) != 1) {
946 static const char errmsg[] = "Parent failed to complete crash dump.\n"; 1078 static const char errmsg[] = "Parent failed to complete crash dump.\n";
947 sys_write(2, errmsg, sizeof(errmsg)-1); 1079 log(errmsg, sizeof(errmsg)-1);
948 } 1080 }
949 1081
950 return true; 1082 return true;
951 } 1083 }
952 1084
953 void EnableNonBrowserCrashDumping() { 1085 void EnableNonBrowserCrashDumping() {
954 const int fd = base::GlobalDescriptors::GetInstance()->Get(kCrashDumpSignal); 1086 const int fd = base::GlobalDescriptors::GetInstance()->Get(kCrashDumpSignal);
955 g_is_crash_reporter_enabled = true; 1087 g_is_crash_reporter_enabled = true;
956 // We deliberately leak this object. 1088 // We deliberately leak this object.
957 DCHECK(!g_breakpad); 1089 DCHECK(!g_breakpad);
958 g_breakpad = new google_breakpad::ExceptionHandler( 1090 g_breakpad = new google_breakpad::ExceptionHandler(
959 "" /* unused */, NULL, NULL, reinterpret_cast<void*>(fd), true); 1091 "" /* unused */, NULL, NULL, reinterpret_cast<void*>(fd), true);
960 g_breakpad->set_crash_handler(NonBrowserCrashHandler); 1092 g_breakpad->set_crash_handler(NonBrowserCrashHandler);
961 } 1093 }
962 1094
963 void InitCrashReporter() { 1095 void InitCrashReporter() {
1096 #if defined(OS_ANDROID)
1097 // This will guarantee that the BuildInfo has been initialized and subsequent
1098 // calls will not require memory allocation.
1099 base::android::BuildInfo::GetInstance();
1100 #endif
964 // Determine the process type and take appropriate action. 1101 // Determine the process type and take appropriate action.
965 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); 1102 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
966 if (parsed_command_line.HasSwitch(switches::kDisableBreakpad)) 1103 if (parsed_command_line.HasSwitch(switches::kDisableBreakpad))
967 return; 1104 return;
968 1105
969 const std::string process_type = 1106 const std::string process_type =
970 parsed_command_line.GetSwitchValueASCII(switches::kProcessType); 1107 parsed_command_line.GetSwitchValueASCII(switches::kProcessType);
971 if (process_type.empty()) { 1108 if (process_type.empty()) {
972 EnableCrashDumping(getenv(env_vars::kHeadless) != NULL); 1109 EnableCrashDumping(getenv(env_vars::kHeadless) != NULL);
973 } else if (process_type == switches::kRendererProcess || 1110 } else if (process_type == switches::kRendererProcess ||
974 process_type == switches::kPluginProcess || 1111 process_type == switches::kPluginProcess ||
975 process_type == switches::kPpapiPluginProcess || 1112 process_type == switches::kPpapiPluginProcess ||
976 process_type == switches::kZygoteProcess || 1113 process_type == switches::kZygoteProcess ||
977 process_type == switches::kGpuProcess) { 1114 process_type == switches::kGpuProcess) {
1115 #if defined(OS_ANDROID)
1116 child_process_logging::SetClientId("Android");
1117 #endif
978 // We might be chrooted in a zygote or renderer process so we cannot call 1118 // 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 1119 // GetCollectStatsConsent because that needs access the the user's home
980 // dir. Instead, we set a command line flag for these processes. 1120 // 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 1121 // Even though plugins are not chrooted, we share the same code path for
982 // simplicity. 1122 // simplicity.
983 if (!parsed_command_line.HasSwitch(switches::kEnableCrashReporter)) 1123 if (!parsed_command_line.HasSwitch(switches::kEnableCrashReporter))
984 return; 1124 return;
Yaron 2012/03/26 18:51:16 Do we always early-return? I thought not, in which
carlosvaldivia 2012/04/03 06:24:47 Isn't that the correct behavior? I would think tha
985 // Get the guid and linux distro from the command line switch. 1125 // Get the guid and linux distro from the command line switch.
986 std::string switch_value = 1126 std::string switch_value =
987 parsed_command_line.GetSwitchValueASCII(switches::kEnableCrashReporter); 1127 parsed_command_line.GetSwitchValueASCII(switches::kEnableCrashReporter);
988 size_t separator = switch_value.find(","); 1128 size_t separator = switch_value.find(",");
989 if (separator != std::string::npos) { 1129 if (separator != std::string::npos) {
990 child_process_logging::SetClientId(switch_value.substr(0, separator)); 1130 child_process_logging::SetClientId(switch_value.substr(0, separator));
991 base::SetLinuxDistro(switch_value.substr(separator + 1)); 1131 base::SetLinuxDistro(switch_value.substr(separator + 1));
992 } else { 1132 } else {
993 child_process_logging::SetClientId(switch_value); 1133 child_process_logging::SetClientId(switch_value);
994 } 1134 }
995 EnableNonBrowserCrashDumping(); 1135 EnableNonBrowserCrashDumping();
996 } 1136 }
997 1137
998 // Set the base process start time value. 1138 // Set the base process start time value.
999 struct timeval tv; 1139 struct timeval tv;
1000 if (!gettimeofday(&tv, NULL)) 1140 if (!gettimeofday(&tv, NULL))
1001 g_process_start_time = timeval_to_ms(&tv); 1141 g_process_start_time = timeval_to_ms(&tv);
1002 else 1142 else
1003 g_process_start_time = 0; 1143 g_process_start_time = 0;
1004 1144
1005 logging::SetDumpWithoutCrashingFunction(&DumpProcess); 1145 logging::SetDumpWithoutCrashingFunction(&DumpProcess);
1006 } 1146 }
1007 1147
1008 bool IsCrashReporterEnabled() { 1148 bool IsCrashReporterEnabled() {
1009 return g_is_crash_reporter_enabled; 1149 return g_is_crash_reporter_enabled;
1010 } 1150 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698