Bug 1481009 Part 2 - Avoid changing exception ports when installing the exception handler in replaying processes, r=gsvelto.
☠☠ backed out by e3cec7443adf ☠ ☠
authorBrian Hackett <bhackett1024@gmail.com>
Wed, 08 Aug 2018 16:44:47 +0000
changeset 486205 58598aa3cf0cf9ea6508314bed448a6fbe3b0654
parent 486204 1ec7f635f4f371bd95b494f68583047d49ca7ee8
child 486206 f7f4127aa9d86a4f7e964e2a2b2131dd149a7c65
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgsvelto
bugs1481009
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1481009 Part 2 - Avoid changing exception ports when installing the exception handler in replaying processes, r=gsvelto.
toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.cc
toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.h
--- a/toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.cc
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.cc
@@ -36,16 +36,18 @@
 #include <map>
 
 #include "mac/handler/exception_handler.h"
 #include "mac/handler/minidump_generator.h"
 #include "common/mac/macho_utilities.h"
 #include "common/mac/scoped_task_suspend-inl.h"
 #include "google_breakpad/common/minidump_exception_mac.h"
 
+#include "mozilla/RecordReplay.h"
+
 #ifndef __EXCEPTIONS
 // This file uses C++ try/catch (but shouldn't). Duplicate the macros from
 // <c++/4.2.1/exception_defines.h> allowing this file to work properly with
 // exceptions disabled even when other C++ libraries are used. #undef the try
 // and catch macros first in case libstdc++ is in use and has already provided
 // its own definitions.
 #undef try
 #define try       if (true)
@@ -632,16 +634,31 @@ void ExceptionHandler::SignalHandler(int
       true,
       true);
 #if USE_PROTECTED_ALLOCATIONS
   if (gBreakpadAllocator)
     gBreakpadAllocator->Protect();
 #endif
 }
 
+// static
+bool ExceptionHandler::WriteForwardedExceptionMinidump(int exception_type,
+						       int exception_code,
+						       int exception_subcode,
+						       mach_port_t thread)
+{
+  if (!gProtectedData.handler) {
+    return false;
+  }
+  return gProtectedData.handler->WriteMinidumpWithException(exception_type, exception_code,
+							    exception_subcode, NULL, thread,
+							    /* exit_after_write = */ false,
+							    /* report_current_thread = */ true);
+}
+
 bool ExceptionHandler::InstallHandler() {
   // If a handler is already installed, something is really wrong.
   if (gProtectedData.handler != NULL) {
     return false;
   }
 
   struct sigaction sa;
   memset(&sa, 0, sizeof(sa));
@@ -668,16 +685,22 @@ bool ExceptionHandler::InstallHandler() 
 #else
     previous_ = new ExceptionParameters();
 #endif
   }
   catch (std::bad_alloc) {
     return false;
   }
 
+  // Don't modify exception ports when replaying, to avoid interfering with the
+  // record/replay system's exception handler.
+  if (mozilla::recordreplay::IsReplaying()) {
+    return true;
+  }
+
   // Save the current exception ports so that we can forward to them
   previous_->count = EXC_TYPES_COUNT;
   mach_port_t current_task = mach_task_self();
   kern_return_t result = task_get_exception_ports(current_task,
                                                   s_exception_mask,
                                                   previous_->masks,
                                                   &previous_->count,
                                                   previous_->ports,
@@ -757,17 +780,19 @@ bool ExceptionHandler::Setup(bool instal
   if (result == KERN_SUCCESS)
     result = mach_port_insert_right(current_task, handler_port_, handler_port_,
                                     MACH_MSG_TYPE_MAKE_SEND);
 
   if (install_handler && result == KERN_SUCCESS)
     if (!InstallHandler())
       return false;
 
-  if (result == KERN_SUCCESS) {
+  // Don't spawn the handler thread when replaying, as we have not set up
+  // exception ports for it to monitor.
+  if (result == KERN_SUCCESS && !mozilla::recordreplay::IsReplaying()) {
     // Install the handler in its own thread, detached as we won't be joining.
     pthread_attr_t attr;
     pthread_attr_init(&attr);
     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
     int thread_create_result = pthread_create(&handler_thread_, &attr,
                                               &WaitForMessage, this);
     pthread_attr_destroy(&attr);
     result = thread_create_result ? KERN_FAILURE : KERN_SUCCESS;
--- a/toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.h
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.h
@@ -150,16 +150,22 @@ class ExceptionHandler {
   // Write a minidump of child immediately. This can be used to capture
   // the execution state of a child process independently of a crash.
   static bool WriteMinidumpForChild(mach_port_t child,
 				    mach_port_t child_blamed_thread,
 				    const std::string &dump_path,
 				    MinidumpCallback callback,
 				    void *callback_context);
 
+  // Write a minidump for an exception that was received by another handler.
+  static bool WriteForwardedExceptionMinidump(int exception_type,
+					      int exception_code,
+					      int exception_subcode,
+					      mach_port_t thread);
+
   // Returns whether out-of-process dump generation is used or not.
   bool IsOutOfProcess() const {
 #if TARGET_OS_IPHONE
     return false;
 #else
     return crash_generation_client_.get() != NULL;
 #endif
   }