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 |