summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authormark@chromium.org <mark@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-03 21:27:36 +0000
committermark@chromium.org <mark@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-03 21:27:36 +0000
commite9a8c19f1f6af2cbfdde08a2884175e521bcef55 (patch)
treed7c807c51b0384379dba1be98c05f8def8804701 /base
parentf26bda5f49ce07483f8033b75c9748a2eaa8ba79 (diff)
downloadchromium_src-e9a8c19f1f6af2cbfdde08a2884175e521bcef55.zip
chromium_src-e9a8c19f1f6af2cbfdde08a2884175e521bcef55.tar.gz
chromium_src-e9a8c19f1f6af2cbfdde08a2884175e521bcef55.tar.bz2
When forking, restore the default exception handler port.
The browser process launches children with fork && exec. On the Mac, this results in a child that has its exception ports set the same as the parent. When Breakpad is enabled, this means that a child such as a renderer process begins its life with its exception port pointing to a Breakpad instance running inside the browser. This is not intended. Even if the child installs its own Breakpad handler (which a renderer would), the previous handler would be pointing to the instance inside the browser, and if the child's Breakpad is misconfigured to pass exceptions to the previous handler it will wind up being passed back to the parent. The misconfiguration was corrected in r25311. This change restores the default exception handler port, which should be Apple Crash Reporter/ReportCrash, in the child process immediately after it it has been forked. BUG=20371 TEST=None, because r25311 fixed the visible aspect of this bug Review URL: http://codereview.chromium.org/200007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@25371 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r--base/process_util.h11
-rw-r--r--base/process_util_mac.mm19
-rw-r--r--base/process_util_posix.cc8
3 files changed, 38 insertions, 0 deletions
diff --git a/base/process_util.h b/base/process_util.h
index 91cca61..17ee3c7 100644
--- a/base/process_util.h
+++ b/base/process_util.h
@@ -414,6 +414,17 @@ void EnableTerminationOnHeapCorruption();
// the current process's scheduling priority to a high priority.
void RaiseProcessToHighPriority();
+#if defined(OS_MACOSX)
+// Restore the default exception handler, setting it to Apple Crash Reporter
+// (ReportCrash). When forking and execing a new process, the child will
+// inherit the parent's exception ports, which may be set to the Breakpad
+// instance running inside the parent. The parent's Breakpad instance should
+// not handle the child's exceptions. Calling RestoreDefaultExceptionHandler
+// in the child after forking will restore the standard exception handler.
+// See http://crbug.com/20371/ for more details.
+void RestoreDefaultExceptionHandler();
+#endif
+
} // namespace base
#endif // BASE_PROCESS_UTIL_H_
diff --git a/base/process_util_mac.mm b/base/process_util_mac.mm
index de9b3f1..da0b200 100644
--- a/base/process_util_mac.mm
+++ b/base/process_util_mac.mm
@@ -7,6 +7,8 @@
#import <Cocoa/Cocoa.h>
#include <crt_externs.h>
+#include <mach/mach_init.h>
+#include <mach/task.h>
#include <spawn.h>
#include <sys/sysctl.h>
#include <sys/types.h>
@@ -21,6 +23,23 @@
namespace base {
+void RestoreDefaultExceptionHandler() {
+ // This function is tailored to remove the Breakpad exception handler.
+ // exception_mask matches s_exception_mask in
+ // breakpad/src/client/mac/handler/exception_handler.cc
+ const exception_mask_t exception_mask = EXC_MASK_BAD_ACCESS |
+ EXC_MASK_BAD_INSTRUCTION |
+ EXC_MASK_ARITHMETIC |
+ EXC_MASK_BREAKPOINT;
+
+ // Setting the exception port to MACH_PORT_NULL may not be entirely
+ // kosher to restore the default exception handler, but in practice,
+ // it results in the exception port being set to Apple Crash Reporter,
+ // the desired behavior.
+ task_set_exception_ports(mach_task_self(), exception_mask, MACH_PORT_NULL,
+ EXCEPTION_DEFAULT, THREAD_STATE_NONE);
+}
+
NamedProcessIterator::NamedProcessIterator(const std::wstring& executable_name,
const ProcessFilter* filter)
: executable_name_(executable_name),
diff --git a/base/process_util_posix.cc b/base/process_util_posix.cc
index 9502ca0..425f455 100644
--- a/base/process_util_posix.cc
+++ b/base/process_util_posix.cc
@@ -233,6 +233,10 @@ bool LaunchApp(const std::vector<std::string>& argv,
if (pid == 0) {
// Child process
+#if defined(OS_MACOSX)
+ RestoreDefaultExceptionHandler();
+#endif
+
InjectiveMultimap fd_shuffle;
for (file_handle_mapping_vector::const_iterator
it = fds_to_remap.begin(); it != fds_to_remap.end(); ++it) {
@@ -520,6 +524,10 @@ bool GetAppOutput(const CommandLine& cl, std::string* output) {
return false;
case 0: // child
{
+#if defined(OS_MACOSX)
+ RestoreDefaultExceptionHandler();
+#endif
+
// Obscure fork() rule: in the child, if you don't end up doing exec*(),
// you call _exit() instead of exit(). This is because _exit() does not
// call any previously-registered (in the parent) exit handlers, which