| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 #include "chrome/app/breakpad_linux.h" | 5 #include "chrome/app/breakpad_linux.h" |
| 6 | 6 |
| 7 #include <arpa/inet.h> | 7 #include <arpa/inet.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <netinet/in.h> | 9 #include <netinet/in.h> |
| 10 #include <stdlib.h> | |
| 11 #include <sys/sendfile.h> | 10 #include <sys/sendfile.h> |
| 12 #include <sys/socket.h> | 11 #include <sys/socket.h> |
| 13 #include <sys/uio.h> | 12 #include <sys/uio.h> |
| 14 #include <sys/wait.h> | 13 #include <sys/wait.h> |
| 15 #include <unistd.h> | 14 #include <unistd.h> |
| 16 | 15 |
| 17 #include <algorithm> | 16 #include <algorithm> |
| 18 #include <string> | 17 #include <string> |
| 19 | 18 |
| 20 #include "base/command_line.h" | 19 #include "base/command_line.h" |
| 21 #include "base/eintr_wrapper.h" | 20 #include "base/eintr_wrapper.h" |
| 22 #include "base/file_path.h" | |
| 23 #include "base/file_version_info_linux.h" | 21 #include "base/file_version_info_linux.h" |
| 24 #include "base/format_macros.h" | 22 #include "base/format_macros.h" |
| 25 #include "base/global_descriptors_posix.h" | 23 #include "base/global_descriptors_posix.h" |
| 26 #include "base/json_writer.h" | 24 #include "base/json_writer.h" |
| 27 #include "base/linux_util.h" | 25 #include "base/linux_util.h" |
| 28 #include "base/path_service.h" | 26 #include "base/path_service.h" |
| 29 #include "base/rand_util.h" | 27 #include "base/rand_util.h" |
| 30 #include "base/scoped_fd.h" | 28 #include "base/scoped_fd.h" |
| 31 #include "base/string_util.h" | 29 #include "base/string_util.h" |
| 32 #include "base/values.h" | 30 #include "base/values.h" |
| 33 #include "breakpad/linux/directory_reader.h" | 31 #include "breakpad/linux/directory_reader.h" |
| 34 #include "breakpad/linux/exception_handler.h" | 32 #include "breakpad/linux/exception_handler.h" |
| 35 #include "breakpad/linux/linux_libc_support.h" | 33 #include "breakpad/linux/linux_libc_support.h" |
| 36 #include "breakpad/linux/linux_syscall_support.h" | 34 #include "breakpad/linux/linux_syscall_support.h" |
| 37 #include "breakpad/linux/memory.h" | 35 #include "breakpad/linux/memory.h" |
| 38 #include "chrome/common/chrome_descriptors.h" | 36 #include "chrome/common/chrome_descriptors.h" |
| 39 #include "chrome/common/chrome_paths.h" | |
| 40 #include "chrome/common/chrome_switches.h" | 37 #include "chrome/common/chrome_switches.h" |
| 41 #include "chrome/installer/util/google_update_settings.h" | 38 #include "chrome/installer/util/google_update_settings.h" |
| 42 | 39 |
| 43 static const char kUploadURL[] = | 40 static const char kUploadURL[] = |
| 44 "https://clients2.google.com/cr/report"; | 41 "https://clients2.google.com/cr/report"; |
| 45 | 42 |
| 46 // Writes the value |v| as 16 hex characters to the memory pointed at by | 43 // Writes the value |v| as 16 hex characters to the memory pointed at by |
| 47 // |output|. | 44 // |output|. |
| 48 static void write_uint64_hex(char* output, uint64_t v) { | 45 static void write_uint64_hex(char* output, uint64_t v) { |
| 49 static const char hextable[] = "0123456789abcdef"; | 46 static const char hextable[] = "0123456789abcdef"; |
| 50 | 47 |
| 51 for (int i = 15; i >= 0; --i) { | 48 for (int i = 15; i >= 0; --i) { |
| 52 output[i] = hextable[v & 15]; | 49 output[i] = hextable[v & 15]; |
| 53 v >>= 4; | 50 v >>= 4; |
| 54 } | 51 } |
| 55 } | 52 } |
| 56 | 53 |
| 57 pid_t HandleCrashDump(const BreakpadInfo& info) { | 54 pid_t UploadCrashDump(const BreakpadInfo& info) { |
| 58 // WARNING: this code runs in a compromised context. It may not call into | 55 // WARNING: this code runs in a compromised context. It may not call into |
| 59 // libc nor allocate memory normally. | 56 // libc nor allocate memory normally. |
| 60 | 57 |
| 61 const int dumpfd = sys_open(info.filename, O_RDONLY, 0); | 58 const int dumpfd = sys_open(info.filename, O_RDONLY, 0); |
| 62 if (dumpfd < 0) { | 59 if (dumpfd < 0) { |
| 63 static const char msg[] = "Cannot upload crash dump: failed to open\n"; | 60 static const char msg[] = "Cannot upload crash dump: failed to open\n"; |
| 64 sys_write(2, msg, sizeof(msg)); | 61 sys_write(2, msg, sizeof(msg)); |
| 65 return -1; | 62 return -1; |
| 66 } | 63 } |
| 67 struct kernel_stat st; | 64 struct kernel_stat st; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 91 const int ufd = sys_open("/dev/urandom", O_RDONLY, 0); | 88 const int ufd = sys_open("/dev/urandom", O_RDONLY, 0); |
| 92 if (ufd < 0) { | 89 if (ufd < 0) { |
| 93 static const char msg[] = "Cannot upload crash dump because /dev/urandom" | 90 static const char msg[] = "Cannot upload crash dump because /dev/urandom" |
| 94 " is missing\n"; | 91 " is missing\n"; |
| 95 sys_write(2, msg, sizeof(msg) - 1); | 92 sys_write(2, msg, sizeof(msg) - 1); |
| 96 return -1; | 93 return -1; |
| 97 } | 94 } |
| 98 | 95 |
| 99 static const char temp_file_template[] = | 96 static const char temp_file_template[] = |
| 100 "/tmp/chromium-upload-XXXXXXXXXXXXXXXX"; | 97 "/tmp/chromium-upload-XXXXXXXXXXXXXXXX"; |
| 101 char temp_file[sizeof(temp_file_template)]; | 98 char buf[sizeof(temp_file_template)]; |
| 99 memcpy(buf, temp_file_template, sizeof(temp_file_template)); |
| 100 |
| 102 int fd = -1; | 101 int fd = -1; |
| 103 if (info.upload) { | 102 for (unsigned i = 0; i < 10; ++i) { |
| 104 memcpy(temp_file, temp_file_template, sizeof(temp_file_template)); | 103 uint64_t t; |
| 104 read(ufd, &t, sizeof(t)); |
| 105 write_uint64_hex(buf + sizeof(buf) - (16 + 1), t); |
| 105 | 106 |
| 106 for (unsigned i = 0; i < 10; ++i) { | 107 fd = sys_open(buf, O_WRONLY | O_CREAT | O_EXCL, 0600); |
| 107 uint64_t t; | 108 if (fd >= 0) |
| 108 read(ufd, &t, sizeof(t)); | 109 break; |
| 109 write_uint64_hex(temp_file + sizeof(temp_file) - (16 + 1), t); | |
| 110 | |
| 111 fd = sys_open(temp_file, O_WRONLY | O_CREAT | O_EXCL, 0600); | |
| 112 if (fd >= 0) | |
| 113 break; | |
| 114 } | |
| 115 | |
| 116 if (fd < 0) { | |
| 117 static const char msg[] = "Failed to create temporary file in /tmp: " | |
| 118 "cannot upload crash dump\n"; | |
| 119 sys_write(2, msg, sizeof(msg) - 1); | |
| 120 sys_close(ufd); | |
| 121 return -1; | |
| 122 } | |
| 123 } else { | |
| 124 fd = sys_open(info.filename, O_WRONLY, 0600); | |
| 125 if (fd < 0) { | |
| 126 static const char msg[] = "Failed to save crash dump: failed to open\n"; | |
| 127 sys_write(2, msg, sizeof(msg) - 1); | |
| 128 sys_close(ufd); | |
| 129 return -1; | |
| 130 } | |
| 131 } | 110 } |
| 132 | 111 |
| 133 // The MIME boundary is 28 hyphens, followed by a 64-bit nonce and a NUL. | 112 if (fd == -1) { |
| 113 static const char msg[] = "Failed to create temporary file in /tmp: cannot " |
| 114 "upload crash dump\n"; |
| 115 sys_write(2, msg, sizeof(msg) - 1); |
| 116 sys_close(ufd); |
| 117 return -1; |
| 118 } |
| 119 |
| 120 // The MIME boundary is 28 hypens, followed by a 64-bit nonce and a NUL. |
| 134 char mime_boundary[28 + 16 + 1]; | 121 char mime_boundary[28 + 16 + 1]; |
| 135 my_memset(mime_boundary, '-', 28); | 122 my_memset(mime_boundary, '-', 28); |
| 136 uint64_t boundary_rand; | 123 uint64_t boundary_rand; |
| 137 sys_read(ufd, &boundary_rand, sizeof(boundary_rand)); | 124 sys_read(ufd, &boundary_rand, sizeof(boundary_rand)); |
| 138 write_uint64_hex(mime_boundary + 28, boundary_rand); | 125 write_uint64_hex(mime_boundary + 28, boundary_rand); |
| 139 mime_boundary[28 + 16] = 0; | 126 mime_boundary[28 + 16] = 0; |
| 140 sys_close(ufd); | 127 sys_close(ufd); |
| 141 | 128 |
| 142 // The define for the product version is a wide string, so we need to | 129 // The define for the product version is a wide string, so we need to |
| 143 // downconvert it. | 130 // downconvert it. |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 iov[8].iov_len = sizeof(mime_boundary) - 1; | 366 iov[8].iov_len = sizeof(mime_boundary) - 1; |
| 380 iov[9].iov_base = const_cast<char*>(dashdash_msg); | 367 iov[9].iov_base = const_cast<char*>(dashdash_msg); |
| 381 iov[9].iov_len = sizeof(dashdash_msg); | 368 iov[9].iov_len = sizeof(dashdash_msg); |
| 382 iov[10].iov_base = const_cast<char*>(rn); | 369 iov[10].iov_base = const_cast<char*>(rn); |
| 383 iov[10].iov_len = sizeof(rn); | 370 iov[10].iov_len = sizeof(rn); |
| 384 | 371 |
| 385 sys_writev(fd, iov, 11); | 372 sys_writev(fd, iov, 11); |
| 386 | 373 |
| 387 sys_close(fd); | 374 sys_close(fd); |
| 388 | 375 |
| 389 if (!info.upload) | |
| 390 return 0; | |
| 391 | |
| 392 // The --header argument to wget looks like: | 376 // The --header argument to wget looks like: |
| 393 // --header=Content-Type: multipart/form-data; boundary=XYZ | 377 // --header=Content-Type: multipart/form-data; boundary=XYZ |
| 394 // where the boundary has two fewer leading '-' chars | 378 // where the boundary has two fewer leading '-' chars |
| 395 static const char header_msg[] = | 379 static const char header_msg[] = |
| 396 "--header=Content-Type: multipart/form-data; boundary="; | 380 "--header=Content-Type: multipart/form-data; boundary="; |
| 397 char* const header = reinterpret_cast<char*>(allocator.Alloc( | 381 char* const header = reinterpret_cast<char*>(allocator.Alloc( |
| 398 sizeof(header_msg) - 1 + sizeof(mime_boundary) - 2)); | 382 sizeof(header_msg) - 1 + sizeof(mime_boundary) - 2)); |
| 399 memcpy(header, header_msg, sizeof(header_msg) - 1); | 383 memcpy(header, header_msg, sizeof(header_msg) - 1); |
| 400 memcpy(header + sizeof(header_msg) - 1, mime_boundary + 2, | 384 memcpy(header + sizeof(header_msg) - 1, mime_boundary + 2, |
| 401 sizeof(mime_boundary) - 2); | 385 sizeof(mime_boundary) - 2); |
| 402 // We grab the NUL byte from the end of |mime_boundary|. | 386 // We grab the NUL byte from the end of |mime_boundary|. |
| 403 | 387 |
| 404 // The --post-file argument to wget looks like: | 388 // The --post-file argument to wget looks like: |
| 405 // --post-file=/tmp/... | 389 // --post-file=/tmp/... |
| 406 static const char post_file_msg[] = "--post-file="; | 390 static const char post_file_msg[] = "--post-file="; |
| 407 char* const post_file = reinterpret_cast<char*>(allocator.Alloc( | 391 char* const post_file = reinterpret_cast<char*>(allocator.Alloc( |
| 408 sizeof(post_file_msg) - 1 + sizeof(temp_file))); | 392 sizeof(post_file_msg) - 1 + sizeof(buf))); |
| 409 memcpy(post_file, post_file_msg, sizeof(post_file_msg) - 1); | 393 memcpy(post_file, post_file_msg, sizeof(post_file_msg) - 1); |
| 410 memcpy(post_file + sizeof(post_file_msg) - 1, temp_file, sizeof(temp_file)); | 394 memcpy(post_file + sizeof(post_file_msg) - 1, buf, sizeof(buf)); |
| 411 | 395 |
| 412 const pid_t child = sys_fork(); | 396 const pid_t child = sys_fork(); |
| 413 if (!child) { | 397 if (!child) { |
| 414 // This code is called both when a browser is crashing (in which case, | 398 // This code is called both when a browser is crashing (in which case, |
| 415 // nothing really matters any more) and when a renderer crashes, in which | 399 // nothing really matters any more) and when a renderer crashes, in which |
| 416 // case we need to continue. | 400 // case we need to continue. |
| 417 // | 401 // |
| 418 // Since we are a multithreaded app, if we were just to fork(), we might | 402 // Since we are a multithreaded app, if we were just to fork(), we might |
| 419 // grab file descriptors which have just been created in another thread and | 403 // grab file descriptors which have just been created in another thread and |
| 420 // hold them open for too long. | 404 // hold them open for too long. |
| (...skipping 29 matching lines...) Expand all Loading... |
| 450 char id_buf[17]; | 434 char id_buf[17]; |
| 451 const int len = HANDLE_EINTR(read(fds[0], id_buf, sizeof(id_buf) - 1)); | 435 const int len = HANDLE_EINTR(read(fds[0], id_buf, sizeof(id_buf) - 1)); |
| 452 if (len > 0) { | 436 if (len > 0) { |
| 453 id_buf[len] = 0; | 437 id_buf[len] = 0; |
| 454 static const char msg[] = "\nCrash dump id: "; | 438 static const char msg[] = "\nCrash dump id: "; |
| 455 sys_write(2, msg, sizeof(msg) - 1); | 439 sys_write(2, msg, sizeof(msg) - 1); |
| 456 sys_write(2, id_buf, my_strlen(id_buf)); | 440 sys_write(2, id_buf, my_strlen(id_buf)); |
| 457 sys_write(2, "\n", 1); | 441 sys_write(2, "\n", 1); |
| 458 } | 442 } |
| 459 sys_unlink(info.filename); | 443 sys_unlink(info.filename); |
| 460 sys_unlink(temp_file); | 444 sys_unlink(buf); |
| 461 sys__exit(0); | 445 sys__exit(0); |
| 462 } | 446 } |
| 463 | 447 |
| 464 sys_close(fds[0]); | 448 sys_close(fds[0]); |
| 465 sys_dup2(fds[1], 3); | 449 sys_dup2(fds[1], 3); |
| 466 static const char* const kWgetBinary = "/usr/bin/wget"; | 450 static const char* const kWgetBinary = "/usr/bin/wget"; |
| 467 const char* args[] = { | 451 const char* args[] = { |
| 468 kWgetBinary, | 452 kWgetBinary, |
| 469 header, | 453 header, |
| 470 post_file, | 454 post_file, |
| 471 kUploadURL, | 455 kUploadURL, |
| 472 "-O", // output reply to fd 3 | 456 "-O", // output reply to fd 3 |
| 473 "/dev/fd/3", | 457 "/dev/fd/3", |
| 474 NULL, | 458 NULL, |
| 475 }; | 459 }; |
| 476 | 460 |
| 477 execv(kWgetBinary, const_cast<char**>(args)); | 461 execv("/usr/bin/wget", const_cast<char**>(args)); |
| 478 static const char msg[] = "Cannot upload crash dump: cannot exec " | 462 static const char msg[] = "Cannot upload crash dump: cannot exec " |
| 479 "/usr/bin/wget\n"; | 463 "/usr/bin/wget\n"; |
| 480 sys_write(2, msg, sizeof(msg) - 1); | 464 sys_write(2, msg, sizeof(msg) - 1); |
| 481 sys__exit(1); | 465 sys__exit(1); |
| 482 } | 466 } |
| 483 | 467 |
| 484 return child; | 468 return child; |
| 485 } | 469 } |
| 486 | 470 |
| 487 // This is defined in chrome/browser/google_update_settings_linux.cc, it's the | 471 // This is defined in chrome/browser/google_update_settings_linux.cc, it's the |
| 488 // static string containing the user's unique GUID. We send this in the crash | 472 // static string containing the user's unique GUID. We send this in the crash |
| 489 // report. | 473 // report. |
| 490 namespace google_update { | 474 namespace google_update { |
| 491 extern std::string linux_guid; | 475 extern std::string linux_guid; |
| 492 } | 476 } |
| 493 | 477 |
| 494 // This is defined in base/linux_util.cc, it's the static string containing the | 478 // This is defined in base/linux_util.cc, it's the static string containing the |
| 495 // user's distro info. We send this in the crash report. | 479 // user's distro info. We send this in the crash report. |
| 496 namespace base { | 480 namespace base { |
| 497 extern std::string linux_distro; | 481 extern std::string linux_distro; |
| 498 } | 482 } |
| 499 | 483 |
| 500 static bool CrashDone(const char* dump_path, | 484 static bool CrashDone(const char* dump_path, |
| 501 const char* minidump_id, | 485 const char* minidump_id, |
| 502 const bool upload, | 486 void* context, |
| 503 const bool succeeded) { | 487 bool succeeded) { |
| 504 // WARNING: this code runs in a compromised context. It may not call into | 488 // WARNING: this code runs in a compromised context. It may not call into |
| 505 // libc nor allocate memory normally. | 489 // libc nor allocate memory normally. |
| 506 if (!succeeded) | 490 if (!succeeded) |
| 507 return false; | 491 return false; |
| 508 | 492 |
| 509 google_breakpad::PageAllocator allocator; | 493 google_breakpad::PageAllocator allocator; |
| 510 const unsigned dump_path_len = my_strlen(dump_path); | 494 const unsigned dump_path_len = my_strlen(dump_path); |
| 511 const unsigned minidump_id_len = my_strlen(minidump_id); | 495 const unsigned minidump_id_len = my_strlen(minidump_id); |
| 512 char *const path = reinterpret_cast<char*>(allocator.Alloc( | 496 char *const path = reinterpret_cast<char*>(allocator.Alloc( |
| 513 dump_path_len + 1 /* '/' */ + minidump_id_len + | 497 dump_path_len + 1 /* '/' */ + minidump_id_len + |
| 514 4 /* ".dmp" */ + 1 /* NUL */)); | 498 4 /* ".dmp" */ + 1 /* NUL */)); |
| 515 memcpy(path, dump_path, dump_path_len); | 499 memcpy(path, dump_path, dump_path_len); |
| 516 path[dump_path_len] = '/'; | 500 path[dump_path_len] = '/'; |
| 517 memcpy(path + dump_path_len + 1, minidump_id, minidump_id_len); | 501 memcpy(path + dump_path_len + 1, minidump_id, minidump_id_len); |
| 518 memcpy(path + dump_path_len + 1 + minidump_id_len, ".dmp", 4); | 502 memcpy(path + dump_path_len + 1 + minidump_id_len, ".dmp", 4); |
| 519 path[dump_path_len + 1 + minidump_id_len + 4] = 0; | 503 path[dump_path_len + 1 + minidump_id_len + 4] = 0; |
| 520 | 504 |
| 521 BreakpadInfo info; | 505 BreakpadInfo info; |
| 522 info.filename = path; | 506 info.filename = path; |
| 523 info.process_type = "browser"; | 507 info.process_type = "browser"; |
| 524 info.process_type_length = 7; | 508 info.process_type_length = 7; |
| 525 info.crash_url = NULL; | 509 info.crash_url = NULL; |
| 526 info.crash_url_length = 0; | 510 info.crash_url_length = 0; |
| 527 info.guid = google_update::linux_guid.data(); | 511 info.guid = google_update::linux_guid.data(); |
| 528 info.guid_length = google_update::linux_guid.length(); | 512 info.guid_length = google_update::linux_guid.length(); |
| 529 info.distro = base::linux_distro.data(); | 513 info.distro = base::linux_distro.data(); |
| 530 info.distro_length = base::linux_distro.length(); | 514 info.distro_length = base::linux_distro.length(); |
| 531 info.upload = upload; | 515 UploadCrashDump(info); |
| 532 HandleCrashDump(info); | |
| 533 | 516 |
| 534 return true; | 517 return true; |
| 535 } | 518 } |
| 536 | 519 |
| 537 // Wrapper script, do not add more code here. | 520 void EnableCrashDumping() { |
| 538 static bool CrashDoneNoUpload(const char* dump_path, | 521 // We leak this object. |
| 539 const char* minidump_id, | |
| 540 void* context, | |
| 541 bool succeeded) { | |
| 542 return CrashDone(dump_path, minidump_id, false, succeeded); | |
| 543 } | |
| 544 | 522 |
| 545 // Wrapper script, do not add more code here. | 523 new google_breakpad::ExceptionHandler("/tmp", NULL, CrashDone, NULL, |
| 546 static bool CrashDoneUpload(const char* dump_path, | 524 true /* install handlers */); |
| 547 const char* minidump_id, | |
| 548 void* context, | |
| 549 bool succeeded) { | |
| 550 return CrashDone(dump_path, minidump_id, true, succeeded); | |
| 551 } | |
| 552 | |
| 553 void EnableCrashDumping(const bool unattended) { | |
| 554 if (unattended) { | |
| 555 FilePath dumps_path("/tmp"); | |
| 556 PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path); | |
| 557 new google_breakpad::ExceptionHandler(dumps_path.value().c_str(), NULL, | |
| 558 CrashDoneNoUpload, NULL, | |
| 559 true /* install handlers */); | |
| 560 } else { | |
| 561 new google_breakpad::ExceptionHandler("/tmp", NULL, CrashDoneUpload, NULL, | |
| 562 true /* install handlers */); | |
| 563 } | |
| 564 } | 525 } |
| 565 | 526 |
| 566 // This is defined in chrome/common/child_process_logging_linux.cc, it's the | 527 // This is defined in chrome/common/child_process_logging_linux.cc, it's the |
| 567 // static string containing the current active URL. We send this in the crash | 528 // static string containing the current active URL. We send this in the crash |
| 568 // report. | 529 // report. |
| 569 namespace child_process_logging { | 530 namespace child_process_logging { |
| 570 extern std::string active_url; | 531 extern std::string active_url; |
| 571 } | 532 } |
| 572 | 533 |
| 573 static bool | 534 static bool |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 633 new google_breakpad::ExceptionHandler("" /* unused */, NULL, NULL, | 594 new google_breakpad::ExceptionHandler("" /* unused */, NULL, NULL, |
| 634 (void*) fd, true); | 595 (void*) fd, true); |
| 635 handler->set_crash_handler(RendererCrashHandler); | 596 handler->set_crash_handler(RendererCrashHandler); |
| 636 } | 597 } |
| 637 | 598 |
| 638 void InitCrashReporter() { | 599 void InitCrashReporter() { |
| 639 // Determine the process type and take appropriate action. | 600 // Determine the process type and take appropriate action. |
| 640 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); | 601 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); |
| 641 const std::wstring process_type = | 602 const std::wstring process_type = |
| 642 parsed_command_line.GetSwitchValue(switches::kProcessType); | 603 parsed_command_line.GetSwitchValue(switches::kProcessType); |
| 643 const bool unattended = (getenv("CHROME_HEADLESS") != NULL); | |
| 644 if (process_type.empty()) { | 604 if (process_type.empty()) { |
| 645 if (!(unattended || GoogleUpdateSettings::GetCollectStatsConsent())) | 605 if (!GoogleUpdateSettings::GetCollectStatsConsent()) |
| 646 return; | 606 return; |
| 647 base::GetLinuxDistro(); // Initialize base::linux_distro if needed. | 607 base::GetLinuxDistro(); // Initialize base::linux_distro if needed. |
| 648 EnableCrashDumping(unattended); | 608 EnableCrashDumping(); |
| 649 } else if (process_type == switches::kRendererProcess || | 609 } else if (process_type == switches::kRendererProcess || |
| 650 process_type == switches::kZygoteProcess) { | 610 process_type == switches::kZygoteProcess) { |
| 651 // We might be chrooted in a zygote or renderer process so we cannot call | 611 // We might be chrooted in a zygote or renderer process so we cannot call |
| 652 // GetCollectStatsConsent because that needs access the the user's home | 612 // GetCollectStatsConsent because that needs access the the user's home |
| 653 // dir. Instead, we set a command line flag for these processes. | 613 // dir. Instead, we set a command line flag for these processes. |
| 654 if (!parsed_command_line.HasSwitch(switches::kEnableCrashReporter)) | 614 if (!parsed_command_line.HasSwitch(switches::kEnableCrashReporter)) |
| 655 return; | 615 return; |
| 656 // Get the guid and linux distro from the command line switch. | 616 // Get the guid and linux distro from the command line switch. |
| 657 std::string switch_value = WideToASCII( | 617 std::string switch_value = WideToASCII( |
| 658 parsed_command_line.GetSwitchValue(switches::kEnableCrashReporter)); | 618 parsed_command_line.GetSwitchValue(switches::kEnableCrashReporter)); |
| 659 size_t separator = switch_value.find(","); | 619 size_t separator = switch_value.find(","); |
| 660 if (separator != std::string::npos) { | 620 if (separator != std::string::npos) { |
| 661 google_update::linux_guid = switch_value.substr(0, separator); | 621 google_update::linux_guid = switch_value.substr(0, separator); |
| 662 base::linux_distro = switch_value.substr(separator + 1); | 622 base::linux_distro = switch_value.substr(separator + 1); |
| 663 } else { | 623 } else { |
| 664 google_update::linux_guid = switch_value; | 624 google_update::linux_guid = switch_value; |
| 665 } | 625 } |
| 666 EnableRendererCrashDumping(); | 626 EnableRendererCrashDumping(); |
| 667 } | 627 } |
| 668 } | 628 } |
| 669 | 629 |
| 670 // ----------------------------------------------------------------------------- | 630 // ----------------------------------------------------------------------------- |
| 671 | 631 |
| 672 #if defined(GOOGLE_CHROME_BUILD) | |
| 673 bool EnableCoreDumping(std::string* core_dump_directory) { | 632 bool EnableCoreDumping(std::string* core_dump_directory) { |
| 674 // First we check that the core files will get dumped to the | 633 // First we check that the core files will get dumped to the |
| 675 // current-directory in a file called 'core'. We could try to support other | 634 // current-directory in a file called 'core'. We could try to support other |
| 676 // setups by simulating the kernel's code, but it's extra complexity and we | 635 // setups by simulating the kernel's code, but it's extra complexity and we |
| 677 // only intend for this code to be run internally. | 636 // only intend for this code to be run internally. |
| 678 static const char kCorePatternFd[] = "/proc/sys/kernel/core_pattern"; | 637 static const char kCorePatternFd[] = "/proc/sys/kernel/core_pattern"; |
| 679 | 638 |
| 680 ScopedFd core_pattern_fd(open(kCorePatternFd, O_RDONLY)); | 639 ScopedFd core_pattern_fd(open(kCorePatternFd, O_RDONLY)); |
| 681 if (core_pattern_fd.get() < 0) { | 640 if (core_pattern_fd.get() < 0) { |
| 682 LOG(WARNING) << "Cannot open " << kCorePatternFd << ": " << strerror(errno); | 641 LOG(WARNING) << "Cannot open " << kCorePatternFd << ": " << strerror(errno); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 763 return; | 722 return; |
| 764 } | 723 } |
| 765 | 724 |
| 766 const uint64_t binary_size = st.st_size; | 725 const uint64_t binary_size = st.st_size; |
| 767 | 726 |
| 768 DictionaryValue header; | 727 DictionaryValue header; |
| 769 header.SetString(L"core-size", StringPrintf("%" PRIu32, core_size)); | 728 header.SetString(L"core-size", StringPrintf("%" PRIu32, core_size)); |
| 770 header.SetString(L"chrome-version", FILE_VERSION); | 729 header.SetString(L"chrome-version", FILE_VERSION); |
| 771 header.SetString(L"binary-size", StringPrintf("%" PRIu64, binary_size)); | 730 header.SetString(L"binary-size", StringPrintf("%" PRIu64, binary_size)); |
| 772 header.SetString(L"user", getenv("USER")); | 731 header.SetString(L"user", getenv("USER")); |
| 732 #if defined(GOOGLE_CHROME_BUILD) |
| 773 header.SetBoolean(L"offical-build", true); | 733 header.SetBoolean(L"offical-build", true); |
| 734 #endif |
| 774 | 735 |
| 775 std::string json; | 736 std::string json; |
| 776 JSONWriter::Write(&header, true /* pretty print */, &json); | 737 JSONWriter::Write(&header, true /* pretty print */, &json); |
| 777 const uint32_t json_size = json.size(); | 738 const uint32_t json_size = json.size(); |
| 778 | 739 |
| 779 ScopedFd sock(socket(PF_INET, SOCK_STREAM, 0)); | 740 ScopedFd sock(socket(PF_INET, SOCK_STREAM, 0)); |
| 780 if (sock.get() < 0) { | 741 if (sock.get() < 0) { |
| 781 LOG(WARNING) << "Cannot open socket: " << strerror(errno); | 742 LOG(WARNING) << "Cannot open socket: " << strerror(errno); |
| 782 return; | 743 return; |
| 783 } | 744 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 819 } | 780 } |
| 820 | 781 |
| 821 if (WIFSIGNALED(status) && WCOREDUMP(status)) { | 782 if (WIFSIGNALED(status) && WCOREDUMP(status)) { |
| 822 std::string core_filename; | 783 std::string core_filename; |
| 823 UploadCoreFile(child, &core_filename); | 784 UploadCoreFile(child, &core_filename); |
| 824 unlink(core_filename.c_str()); | 785 unlink(core_filename.c_str()); |
| 825 } | 786 } |
| 826 | 787 |
| 827 rmdir(core_dump_directory.c_str()); | 788 rmdir(core_dump_directory.c_str()); |
| 828 } | 789 } |
| 829 #endif | |
| OLD | NEW |