| 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 <fcntl.h> | 7 #include <fcntl.h> |
| 8 #include <stdlib.h> | 8 #include <stdlib.h> |
| 9 #include <sys/socket.h> | 9 #include <sys/socket.h> |
| 10 #include <sys/time.h> | 10 #include <sys/time.h> |
| (...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 // --post-file=/tmp/... | 443 // --post-file=/tmp/... |
| 444 static const char post_file_msg[] = "--post-file="; | 444 static const char post_file_msg[] = "--post-file="; |
| 445 char* const post_file = reinterpret_cast<char*>(allocator.Alloc( | 445 char* const post_file = reinterpret_cast<char*>(allocator.Alloc( |
| 446 sizeof(post_file_msg) - 1 + sizeof(temp_file))); | 446 sizeof(post_file_msg) - 1 + sizeof(temp_file))); |
| 447 memcpy(post_file, post_file_msg, sizeof(post_file_msg) - 1); | 447 memcpy(post_file, post_file_msg, sizeof(post_file_msg) - 1); |
| 448 memcpy(post_file + sizeof(post_file_msg) - 1, temp_file, sizeof(temp_file)); | 448 memcpy(post_file + sizeof(post_file_msg) - 1, temp_file, sizeof(temp_file)); |
| 449 | 449 |
| 450 const pid_t child = sys_fork(); | 450 const pid_t child = sys_fork(); |
| 451 if (!child) { | 451 if (!child) { |
| 452 // This code is called both when a browser is crashing (in which case, | 452 // This code is called both when a browser is crashing (in which case, |
| 453 // nothing really matters any more) and when a renderer crashes, in which | 453 // nothing really matters any more) and when a renderer/plugin crashes, in |
| 454 // case we need to continue. | 454 // which case we need to continue. |
| 455 // | 455 // |
| 456 // Since we are a multithreaded app, if we were just to fork(), we might | 456 // Since we are a multithreaded app, if we were just to fork(), we might |
| 457 // grab file descriptors which have just been created in another thread and | 457 // grab file descriptors which have just been created in another thread and |
| 458 // hold them open for too long. | 458 // hold them open for too long. |
| 459 // | 459 // |
| 460 // Thus, we have to loop and try and close everything. | 460 // Thus, we have to loop and try and close everything. |
| 461 const int fd = sys_open("/proc/self/fd", O_DIRECTORY | O_RDONLY, 0); | 461 const int fd = sys_open("/proc/self/fd", O_DIRECTORY | O_RDONLY, 0); |
| 462 if (fd < 0) { | 462 if (fd < 0) { |
| 463 for (unsigned i = 3; i < 8192; ++i) | 463 for (unsigned i = 3; i < 8192; ++i) |
| 464 sys_close(i); | 464 sys_close(i); |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 601 } | 601 } |
| 602 } | 602 } |
| 603 | 603 |
| 604 // This is defined in chrome/common/child_process_logging_linux.cc, it's the | 604 // This is defined in chrome/common/child_process_logging_linux.cc, it's the |
| 605 // static string containing the current active URL. We send this in the crash | 605 // static string containing the current active URL. We send this in the crash |
| 606 // report. | 606 // report. |
| 607 namespace child_process_logging { | 607 namespace child_process_logging { |
| 608 extern std::string active_url; | 608 extern std::string active_url; |
| 609 } | 609 } |
| 610 | 610 |
| 611 // Currently Non-Browser = Renderer and Plugins |
| 611 static bool | 612 static bool |
| 612 RendererCrashHandler(const void* crash_context, size_t crash_context_size, | 613 NonBrowserCrashHandler(const void* crash_context, size_t crash_context_size, |
| 613 void* context) { | 614 void* context) { |
| 614 const int fd = reinterpret_cast<intptr_t>(context); | 615 const int fd = reinterpret_cast<intptr_t>(context); |
| 615 int fds[2]; | 616 int fds[2]; |
| 616 socketpair(AF_UNIX, SOCK_STREAM, 0, fds); | 617 socketpair(AF_UNIX, SOCK_STREAM, 0, fds); |
| 617 char guid[kGuidSize + 1] = {0}; | 618 char guid[kGuidSize + 1] = {0}; |
| 618 char crash_url[kMaxActiveURLSize + 1] = {0}; | 619 char crash_url[kMaxActiveURLSize + 1] = {0}; |
| 619 char distro[kDistroSize + 1] = {0}; | 620 char distro[kDistroSize + 1] = {0}; |
| 620 const size_t guid_len = std::min(google_update::posix_guid.size(), | 621 const size_t guid_len = std::min(google_update::posix_guid.size(), |
| 621 kGuidSize); | 622 kGuidSize); |
| 622 const size_t crash_url_len = | 623 const size_t crash_url_len = |
| 623 std::min(child_process_logging::active_url.size(), kMaxActiveURLSize); | 624 std::min(child_process_logging::active_url.size(), kMaxActiveURLSize); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 | 658 |
| 658 HANDLE_EINTR(sys_sendmsg(fd, &msg, 0)); | 659 HANDLE_EINTR(sys_sendmsg(fd, &msg, 0)); |
| 659 sys_close(fds[1]); | 660 sys_close(fds[1]); |
| 660 | 661 |
| 661 char b; | 662 char b; |
| 662 HANDLE_EINTR(sys_read(fds[0], &b, 1)); | 663 HANDLE_EINTR(sys_read(fds[0], &b, 1)); |
| 663 | 664 |
| 664 return true; | 665 return true; |
| 665 } | 666 } |
| 666 | 667 |
| 667 void EnableRendererCrashDumping() { | 668 void EnableNonBrowserCrashDumping() { |
| 668 const int fd = Singleton<base::GlobalDescriptors>()->Get(kCrashDumpSignal); | 669 const int fd = Singleton<base::GlobalDescriptors>()->Get(kCrashDumpSignal); |
| 669 // We deliberately leak this object. | 670 // We deliberately leak this object. |
| 670 google_breakpad::ExceptionHandler* handler = | 671 google_breakpad::ExceptionHandler* handler = |
| 671 new google_breakpad::ExceptionHandler("" /* unused */, NULL, NULL, | 672 new google_breakpad::ExceptionHandler("" /* unused */, NULL, NULL, |
| 672 (void*) fd, true); | 673 (void*) fd, true); |
| 673 handler->set_crash_handler(RendererCrashHandler); | 674 handler->set_crash_handler(NonBrowserCrashHandler); |
| 674 } | 675 } |
| 675 | 676 |
| 676 void InitCrashReporter() { | 677 void InitCrashReporter() { |
| 677 // Determine the process type and take appropriate action. | 678 // Determine the process type and take appropriate action. |
| 678 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); | 679 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); |
| 679 const std::string process_type = | 680 const std::string process_type = |
| 680 parsed_command_line.GetSwitchValueASCII(switches::kProcessType); | 681 parsed_command_line.GetSwitchValueASCII(switches::kProcessType); |
| 681 const bool unattended = (getenv("CHROME_HEADLESS") != NULL); | 682 const bool unattended = (getenv("CHROME_HEADLESS") != NULL); |
| 682 if (process_type.empty()) { | 683 if (process_type.empty()) { |
| 683 if (!(unattended || GoogleUpdateSettings::GetCollectStatsConsent())) | 684 if (!(unattended || GoogleUpdateSettings::GetCollectStatsConsent())) |
| 684 return; | 685 return; |
| 685 EnableCrashDumping(unattended); | 686 EnableCrashDumping(unattended); |
| 686 } else if (process_type == switches::kRendererProcess || | 687 } else if (process_type == switches::kRendererProcess || |
| 688 process_type == switches::kPluginProcess || |
| 687 process_type == switches::kZygoteProcess) { | 689 process_type == switches::kZygoteProcess) { |
| 688 // We might be chrooted in a zygote or renderer process so we cannot call | 690 // We might be chrooted in a zygote or renderer process so we cannot call |
| 689 // GetCollectStatsConsent because that needs access the the user's home | 691 // GetCollectStatsConsent because that needs access the the user's home |
| 690 // dir. Instead, we set a command line flag for these processes. | 692 // dir. Instead, we set a command line flag for these processes. |
| 693 // Even though plugins are not chrooted, we share the same code path for |
| 694 // simplicity. |
| 691 if (!parsed_command_line.HasSwitch(switches::kEnableCrashReporter)) | 695 if (!parsed_command_line.HasSwitch(switches::kEnableCrashReporter)) |
| 692 return; | 696 return; |
| 693 // Get the guid and linux distro from the command line switch. | 697 // Get the guid and linux distro from the command line switch. |
| 694 std::string switch_value = WideToASCII( | 698 std::string switch_value = WideToASCII( |
| 695 parsed_command_line.GetSwitchValue(switches::kEnableCrashReporter)); | 699 parsed_command_line.GetSwitchValue(switches::kEnableCrashReporter)); |
| 696 size_t separator = switch_value.find(","); | 700 size_t separator = switch_value.find(","); |
| 697 if (separator != std::string::npos) { | 701 if (separator != std::string::npos) { |
| 698 google_update::posix_guid = switch_value.substr(0, separator); | 702 google_update::posix_guid = switch_value.substr(0, separator); |
| 699 base::linux_distro = switch_value.substr(separator + 1); | 703 base::linux_distro = switch_value.substr(separator + 1); |
| 700 } else { | 704 } else { |
| 701 google_update::posix_guid = switch_value; | 705 google_update::posix_guid = switch_value; |
| 702 } | 706 } |
| 703 EnableRendererCrashDumping(); | 707 EnableNonBrowserCrashDumping(); |
| 704 } | 708 } |
| 705 | 709 |
| 706 // Set the base process uptime value. | 710 // Set the base process uptime value. |
| 707 struct timeval tv; | 711 struct timeval tv; |
| 708 if (!gettimeofday(&tv, NULL)) | 712 if (!gettimeofday(&tv, NULL)) |
| 709 uptime = tv.tv_sec; | 713 uptime = tv.tv_sec; |
| 710 else | 714 else |
| 711 uptime = 0; | 715 uptime = 0; |
| 712 } | 716 } |
| OLD | NEW |