diff options
author | mark@chromium.org <mark@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2011-10-05 21:58:10 +0000 |
---|---|---|
committer | mark@chromium.org <mark@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e> | 2011-10-05 21:58:10 +0000 |
commit | 1e9dbde88a0f7cdcaba556a24fa468627d5c7e84 (patch) | |
tree | 7752ebf24d2f49ad82936ec68e257c5a58d99034 /src/client/mac | |
parent | Use a bootstrap subset port for the inspector, tying the subset to the (diff) | |
download | breakpad-1e9dbde88a0f7cdcaba556a24fa468627d5c7e84.tar.xz |
Ensure crash reports will be uploaded on the Mac.
Regression from Breakpad r842 (Chromium r103778) - browser crash reports were
uploaded, but renderer crash reports were not. Messages such as these may have
been logged:
com.apple.launchd.peruser.x[y] could not lookup DNS configuration info
service: (ipc/send) invalid destination port
com.apple.launchd.peruser.x[y] Breakpad Reporter: Send Error: Error
Domain=NSURLErrorDomain Code=-1009 UserInfo=z "This computer’s Internet
connection appears to be offline." Underlying Error=(Error
Domain=kCFErrorDomainCFNetwork Code=-1009 UserInfo=w "This computer’s Internet
connection appears to be offline.")
When OnDemandServer establishes the bootstrap subset, it will now register the
parent bootstrap port in the subset namespace so that the Inspector can
recover this port and switch to it. The Sender, launched by the Inspector,
relies on the bootstrap port being set properly.
BUG=chromium:99252
TEST=All test cases from Chromium r103778 (bug chromium:28547) plus:
about:crash should generate a crash report which should be uploaded,
provided that throttling is not in effect. Remove or edit
~/Library/Preferences/com.Breakpad.crash_report_sender.plist to defeat
throttling. Also verify that about:inducebrowsercrashforrealz works.
Review URL: http://breakpad.appspot.com/307001
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@843 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/client/mac')
-rw-r--r-- | src/client/mac/Framework/OnDemandServer.mm | 15 | ||||
-rw-r--r-- | src/client/mac/crash_generation/Inspector.h | 18 | ||||
-rw-r--r-- | src/client/mac/crash_generation/Inspector.mm | 43 |
3 files changed, 74 insertions, 2 deletions
diff --git a/src/client/mac/Framework/OnDemandServer.mm b/src/client/mac/Framework/OnDemandServer.mm index 03f54c44..f736abd4 100644 --- a/src/client/mac/Framework/OnDemandServer.mm +++ b/src/client/mac/Framework/OnDemandServer.mm @@ -86,6 +86,21 @@ kern_return_t OnDemandServer::Initialize(const char *server_command, return kr; } + // The inspector will be invoked with its bootstrap port set to the subset, + // but the sender will need access to the original bootstrap port. Although + // the original port is the subset's parent, bootstrap_parent can't be used + // because it requires extra privileges. Stash the original bootstrap port + // in the subset by registering it under a known name. The inspector will + // recover this port and set it as its own bootstrap port in Inspector.mm + // Inspector::ResetBootstrapPort. + kr = bootstrap_register(bootstrap_subset_port, + const_cast<char*>("BootstrapParentPort"), + bootstrap_port); + if (kr != KERN_SUCCESS) { + PRINT_BOOTSTRAP_RESULT(kr, "bootstrap_register(): "); + return kr; + } + kr = bootstrap_create_server(bootstrap_subset_port, const_cast<char*>(server_command), geteuid(), // server uid diff --git a/src/client/mac/crash_generation/Inspector.h b/src/client/mac/crash_generation/Inspector.h index 9d93b2a7..e6705819 100644 --- a/src/client/mac/crash_generation/Inspector.h +++ b/src/client/mac/crash_generation/Inspector.h @@ -33,6 +33,8 @@ #import "common/mac/SimpleStringDictionary.h" #import <Foundation/Foundation.h> +#include <mach/mach.h> + #import "client/mac/handler/minidump_generator.h" #define VERBOSE 0 @@ -163,6 +165,18 @@ class Inspector { void Inspect(const char *receive_port_name); private: + // The Inspector is invoked with its bootstrap port set to the bootstrap + // subset established in OnDemandServer.mm OnDemandServer::Initialize. + // For proper communication with the system, the sender (which will inherit + // the Inspector's bootstrap port) needs the per-session bootstrap namespace + // available directly in its bootstrap port. OnDemandServer stashed this + // port into the subset namespace under a special name. ResetBootstrapPort + // recovers this port and switches this task to use it as its own bootstrap + // (ensuring that children like the sender will inherit it), and saves the + // subset in bootstrap_subset_port_ for use by ServiceCheckIn and + // ServiceCheckOut. + void ResetBootstrapPort(); + kern_return_t ServiceCheckIn(const char *receive_port_name); kern_return_t ServiceCheckOut(const char *receive_port_name); @@ -174,6 +188,10 @@ class Inspector { void SetCrashTimeParameters(); + // The bootstrap port in which the inspector is registered and into which it + // must check in. + mach_port_t bootstrap_subset_port_; + mach_port_t service_rcv_port_; int exception_type_; diff --git a/src/client/mac/crash_generation/Inspector.mm b/src/client/mac/crash_generation/Inspector.mm index 1b0b97cb..77187082 100644 --- a/src/client/mac/crash_generation/Inspector.mm +++ b/src/client/mac/crash_generation/Inspector.mm @@ -203,6 +203,8 @@ void ConfigFile::WriteFile(const SimpleStringDictionary *configurationParameters //============================================================================= void Inspector::Inspect(const char *receive_port_name) { + ResetBootstrapPort(); + kern_return_t result = ServiceCheckIn(receive_port_name); if (result == KERN_SUCCESS) { @@ -241,10 +243,47 @@ void Inspector::Inspect(const char *receive_port_name) { } //============================================================================= +void Inspector::ResetBootstrapPort() { + // A reasonable default, in case anything fails. + bootstrap_subset_port_ = bootstrap_port; + + mach_port_t self_task = mach_task_self(); + + kern_return_t kr = task_get_bootstrap_port(self_task, + &bootstrap_subset_port_); + if (kr != KERN_SUCCESS) { + NSLog(@"ResetBootstrapPort: task_get_bootstrap_port failed: %s (%d)", + mach_error_string(kr), kr); + return; + } + + mach_port_t bootstrap_parent_port; + kr = bootstrap_look_up(bootstrap_subset_port_, + "BootstrapParentPort", + &bootstrap_parent_port); + if (kr != KERN_SUCCESS) { + NSLog(@"ResetBootstrapPort: bootstrap_look_up failed: %s (%d)", + bootstrap_strerror(kr), kr); + return; + } + + kr = task_set_bootstrap_port(self_task, bootstrap_parent_port); + if (kr != KERN_SUCCESS) { + NSLog(@"ResetBootstrapPort: task_set_bootstrap_port failed: %s (%d)", + mach_error_string(kr), kr); + return; + } + + // Some things access the bootstrap port through this global variable + // instead of calling task_get_bootstrap_port. + bootstrap_port = bootstrap_parent_port; +} + +//============================================================================= kern_return_t Inspector::ServiceCheckIn(const char *receive_port_name) { // We need to get the mach port representing this service, so we can // get information from the crashed process. - kern_return_t kr = bootstrap_check_in(bootstrap_port, + kern_return_t kr = bootstrap_check_in(bootstrap_subset_port_, (char*)receive_port_name, &service_rcv_port_); @@ -275,7 +314,7 @@ kern_return_t Inspector::ServiceCheckOut(const char *receive_port_name) { } // Unregister the service associated with the receive port. - kr = bootstrap_register(bootstrap_port, + kr = bootstrap_register(bootstrap_subset_port_, (char*)receive_port_name, MACH_PORT_NULL); |