Merge mozilla-central to mozilla-inbound. a=merge
authorCosmin Sabou <csabou@mozilla.com>
Sun, 12 Aug 2018 15:01:59 +0300
changeset 431159 935abf820aeb
parent 431158 ecfef1d46f56 (current diff)
parent 431137 e3cec7443adf (diff)
child 431160 49daf4d2dee7
push id34429
push usercbrindusan@mozilla.com
push dateSun, 12 Aug 2018 21:49:33 +0000
treeherdermozilla-central@83d0673bbca4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
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
Merge mozilla-central to mozilla-inbound. a=merge
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -142,16 +142,17 @@
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIMemoryInfoDumper.h"
 #include "nsIMemoryReporter.h"
 #include "nsIMozBrowserFrame.h"
 #include "nsIMutable.h"
 #include "nsIObserverService.h"
 #include "nsIParentChannel.h"
 #include "nsIPresShell.h"
+#include "nsIPromptService.h"
 #include "nsIRemoteWindowContext.h"
 #include "nsIScriptError.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsISiteSecurityService.h"
 #include "nsISound.h"
 #include "nsISpellChecker.h"
 #include "nsIStringBundle.h"
 #include "nsISupportsPrimitives.h"
@@ -5231,16 +5232,28 @@ ContentParent::RecvGraphicsError(const n
     std::stringstream message;
     message << "CP+" << aError.get();
     lf->UpdateStringsVector(message.str());
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
+ContentParent::RecvRecordReplayFatalError(const nsCString& aError)
+{
+  nsCOMPtr<nsIPromptService> promptService(do_GetService(NS_PROMPTSERVICE_CONTRACTID));
+  MOZ_RELEASE_ASSERT(promptService);
+
+  nsAutoCString str(aError);
+  promptService->Alert(nullptr, u"Fatal Record/Replay Error", NS_ConvertUTF8toUTF16(str).get());
+
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
 ContentParent::RecvBeginDriverCrashGuard(const uint32_t& aGuardType, bool* aOutCrashed)
 {
   // Only one driver crash guard should be active at a time, per-process.
   MOZ_ASSERT(!mDriverCrashGuard);
 
   UniquePtr<gfx::DriverCrashGuard> guard;
   switch (gfx::CrashGuardType(aGuardType)) {
   case gfx::CrashGuardType::D3D11Layers:
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -1150,16 +1150,18 @@ public:
                                                           const TabId& aTabId,
                                                           layers::LayersId* aId) override;
 
   virtual mozilla::ipc::IPCResult RecvDeallocateLayerTreeId(const ContentParentId& aCpId,
                                                             const layers::LayersId& aId) override;
 
   virtual mozilla::ipc::IPCResult RecvGraphicsError(const nsCString& aError) override;
 
+  virtual mozilla::ipc::IPCResult RecvRecordReplayFatalError(const nsCString& aError) override;
+
   virtual mozilla::ipc::IPCResult
   RecvBeginDriverCrashGuard(const uint32_t& aGuardType,
                             bool* aOutCrashed) override;
 
   virtual mozilla::ipc::IPCResult RecvEndDriverCrashGuard(const uint32_t& aGuardType) override;
 
   virtual mozilla::ipc::IPCResult RecvAddIdleObserver(const uint64_t& observerId,
                                                       const uint32_t& aIdleTimeInS) override;
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -933,16 +933,19 @@ parent:
     async RecordingDeviceEvents(nsString recordingStatus,
                                 nsString pageURL,
                                 bool isAudio,
                                 bool isVideo);
 
     // Graphics errors
     async GraphicsError(nsCString aError);
 
+    // Record/replay errors.
+    async RecordReplayFatalError(nsCString aError);
+
     // Driver crash guards. aGuardType must be a member of CrashGuardType.
     sync BeginDriverCrashGuard(uint32_t aGuardType) returns (bool crashDetected);
     sync EndDriverCrashGuard(uint32_t aGuardType);
 
     async AddIdleObserver(uint64_t observerId, uint32_t idleTimeInS);
     async RemoveIdleObserver(uint64_t observerId, uint32_t idleTimeInS);
 
     /**
--- a/toolkit/crashreporter/CrashAnnotations.yaml
+++ b/toolkit/crashreporter/CrashAnnotations.yaml
@@ -573,21 +573,16 @@ ProxyStreamUnmarshalStatus:
     the various value this annotation can take.
   type: string
 
 ProxyStreamValid:
   description: >
     Set to "false" when encountering an invalid IPC proxy stream.
   type: string
 
-RecordReplayError:
-  description: >
-    Any fatal error that occurred while recording/replaying a tab.
-  type: string
-
 ReleaseChannel:
   description: >
     Application release channel (e.g. default, beta, ...)
   type: string
   ping: true
 
 RemoteType:
   description: >
--- a/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_client.cc
+++ b/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_client.cc
@@ -27,18 +27,16 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "mac/crash_generation/crash_generation_client.h"
 
 #include "mac/crash_generation/crash_generation_server.h"
 #include "common/mac/MachIPC.h"
 
-#include "mozilla/recordreplay/ChildIPC.h"
-
 namespace google_breakpad {
 
 bool CrashGenerationClient::RequestDumpForException(
     int exception_type,
     int exception_code,
     int exception_subcode,
     mach_port_t crashing_thread) {
   // The server will send a message to this port indicating that it
@@ -50,24 +48,16 @@ bool CrashGenerationClient::RequestDumpF
   message.AddDescriptor(crashing_thread);             // crashing thread
   message.AddDescriptor(MACH_PORT_NULL);              // handler thread
   message.AddDescriptor(acknowledge_port.GetPort());  // message receive port
 
   ExceptionInfo info;
   info.exception_type = exception_type;
   info.exception_code = exception_code;
   info.exception_subcode = exception_subcode;
-  info.child_pid = getpid();
-
-  // When recording/replaying, associate minidumps with the middleman process
-  // so that the UI process can find them.
-  if (mozilla::recordreplay::IsRecordingOrReplaying()) {
-    info.child_pid = mozilla::recordreplay::child::MiddlemanProcessId();
-  }
-
   message.SetData(&info, sizeof(info));
 
   const mach_msg_timeout_t kSendTimeoutMs = 2 * 1000;
   kern_return_t result = sender_.SendMessage(message, kSendTimeoutMs);
   if (result != KERN_SUCCESS)
     return false;
 
   // Give the server slightly longer to reply since it has to
--- a/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.cc
+++ b/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.cc
@@ -105,17 +105,19 @@ bool CrashGenerationServer::WaitForOneMe
     switch (message.GetMessageID()) {
       case kDumpRequestMessage: {
         ExceptionInfo &info = (ExceptionInfo &)*message.GetData();
       
         mach_port_t remote_task = message.GetTranslatedPort(0);
         mach_port_t crashing_thread = message.GetTranslatedPort(1);
         mach_port_t handler_thread = message.GetTranslatedPort(2);
         mach_port_t ack_port = message.GetTranslatedPort(3);
-        ClientInfo client(info.child_pid);
+        pid_t remote_pid = -1;
+        pid_for_task(remote_task, &remote_pid);
+        ClientInfo client(remote_pid);
 
         bool result;
         std::string dump_path;
         if (generate_dumps_ && (!filter_ || filter_(filter_context_))) {
           ScopedTaskSuspend suspend(remote_task);
 
           MinidumpGenerator generator(remote_task, handler_thread);
           dump_path = generator.UniqueNameInDirectory(dump_dir_, NULL);
--- a/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.h
+++ b/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.h
@@ -47,17 +47,16 @@ enum {
   kQuitMessage            = 3
 };
 
 // Exception details sent by the client when requesting a dump.
 struct ExceptionInfo {
   int32_t exception_type;
   int32_t exception_code;
   int32_t exception_subcode;
-  int32_t child_pid;
 };
 
 class CrashGenerationServer {
  public:
   // WARNING: callbacks may be invoked on a different thread
   // than that which creates the CrashGenerationServer.  They must
   // be thread safe.
   typedef void (*OnClientDumpRequestCallback)(void *context,
--- a/toolkit/crashreporter/breakpad-client/mac/crash_generation/moz.build
+++ b/toolkit/crashreporter/breakpad-client/mac/crash_generation/moz.build
@@ -7,15 +7,14 @@
 UNIFIED_SOURCES += [
     'crash_generation_client.cc',
     'crash_generation_server.cc',
 ]
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
-    '/ipc/chromium/src',
     '/toolkit/crashreporter/breakpad-client',
     '/toolkit/crashreporter/google-breakpad/src',
 ]
 
 if CONFIG['CC_TYPE'] == 'clang':
     CXXFLAGS += ['-Wno-shadow']
--- a/toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.cc
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/exception_handler.cc
@@ -36,18 +36,16 @@
 #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)
@@ -634,31 +632,16 @@ 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));
@@ -685,22 +668,16 @@ 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,
@@ -780,19 +757,17 @@ 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;
 
-  // 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()) {
+  if (result == KERN_SUCCESS) {
     // 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,22 +150,16 @@ 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
   }
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -89,17 +89,16 @@ using mozilla::InjectCrashRunnable;
 #include "nsCRT.h"
 #include "nsIFile.h"
 #include <map>
 #include <vector>
 
 #include "mozilla/IOInterposer.h"
 #include "mozilla/mozalloc_oom.h"
 #include "mozilla/WindowsDllBlocklist.h"
-#include "mozilla/recordreplay/ParentIPC.h"
 
 #if defined(XP_MACOSX)
 CFStringRef reporterClientAppID = CFSTR("org.mozilla.crashreporter");
 #endif
 #if defined(MOZ_WIDGET_ANDROID)
 #include "common/linux/file_id.h"
 #endif
 
@@ -3248,34 +3247,16 @@ OnChildProcessDumpRequested(void* aConte
     }
 #ifdef MOZ_CRASHREPORTER_INJECTOR
     if (runCallback)
       NS_DispatchToMainThread(new ReportInjectedCrash(pid));
 #endif
   }
 }
 
-#ifdef XP_MACOSX
-
-// Middleman processes do not have their own crash generation server.
-// Any crashes in the middleman's children are forwarded to the UI process.
-static bool
-MaybeForwardCrashesIfMiddleman()
-{
-  if (recordreplay::IsMiddleman()) {
-    childCrashNotifyPipe =
-      mozilla::Smprintf("gecko-crash-server-pipe.%i",
-                        static_cast<int>(recordreplay::parent::ParentProcessId())).release();
-    return true;
-  }
-  return false;
-}
-
-#endif // XP_MACOSX
-
 static bool
 OOPInitialized()
 {
   return pidToMinidump != nullptr;
 }
 
 void
 OOPInit()
@@ -3354,20 +3335,16 @@ OOPInit()
   crashServer = new CrashGenerationServer(
     serverSocketFd,
     OnChildProcessDumpRequested, nullptr,
     nullptr, nullptr,           // we don't care about process exit here
     true,
     &dumpPath);
 
 #elif defined(XP_MACOSX)
-  if (MaybeForwardCrashesIfMiddleman()) {
-    return;
-  }
-
   childCrashNotifyPipe =
     mozilla::Smprintf("gecko-crash-server-pipe.%i",
                static_cast<int>(getpid())).release();
   const std::string dumpPath = gExceptionHandler->dump_path();
 
   crashServer = new CrashGenerationServer(
     childCrashNotifyPipe,
     nullptr,
--- a/toolkit/recordreplay/Callback.cpp
+++ b/toolkit/recordreplay/Callback.cpp
@@ -122,17 +122,19 @@ PassThroughThreadEventsAllowCallbacks(co
       child::EndIdleTime();
     }
     thread->SetPassThrough(false);
     thread->Events().RecordOrReplayThreadEvent(ThreadEvent::CallbacksFinished);
   } else {
     while (true) {
       ThreadEvent ev = (ThreadEvent) thread->Events().ReadScalar();
       if (ev != ThreadEvent::ExecuteCallback) {
-        MOZ_RELEASE_ASSERT(ev == ThreadEvent::CallbacksFinished);
+        if (ev != ThreadEvent::CallbacksFinished) {
+          child::ReportFatalError("Unexpected event while replaying callback events");
+        }
         break;
       }
       size_t id = thread->Events().ReadScalar();
       ReplayInvokeCallback(id);
     }
   }
 }
 
--- a/toolkit/recordreplay/DirtyMemoryHandler.cpp
+++ b/toolkit/recordreplay/DirtyMemoryHandler.cpp
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "DirtyMemoryHandler.h"
 
-#include "ipc/ChildInternal.h"
+#include "ipc/ChildIPC.h"
 #include "mozilla/Sprintf.h"
 #include "MemorySnapshot.h"
 #include "Thread.h"
 
 #include <mach/exc.h>
 #include <mach/mach.h>
 #include <mach/mach_vm.h>
 #include <sys/time.h>
@@ -60,25 +60,21 @@ DirtyMemoryExceptionHandlerThread(void*)
         request.body.Head.msgh_id == sExceptionId &&
         request.body.exception == EXC_BAD_ACCESS &&
         request.body.codeCnt == 2)
     {
       uint8_t* faultingAddress = (uint8_t*) request.body.code[1];
       if (HandleDirtyMemoryFault(faultingAddress)) {
         replyCode = KERN_SUCCESS;
       } else {
-        child::MinidumpInfo info(request.body.exception,
-                                 request.body.code[0], request.body.code[1],
-                                 request.body.thread.name);
-        child::ReportFatalError(Some(info), "HandleDirtyMemoryFault failed %p %s",
-                                faultingAddress, gMozCrashReason ? gMozCrashReason : "");
+        child::ReportFatalError("HandleDirtyMemoryFault failed %p %s", faultingAddress,
+                                gMozCrashReason ? gMozCrashReason : "");
       }
     } else {
-      child::ReportFatalError(Nothing(),
-                              "DirtyMemoryExceptionHandlerThread mach_msg returned unexpected data");
+      child::ReportFatalError("DirtyMemoryExceptionHandlerThread mach_msg returned unexpected data");
     }
 
     __Reply__exception_raise_t reply;
     reply.Head.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(request.body.Head.msgh_bits), 0);
     reply.Head.msgh_size = sizeof(reply);
     reply.Head.msgh_remote_port = request.body.Head.msgh_remote_port;
     reply.Head.msgh_local_port = MACH_PORT_NULL;
     reply.Head.msgh_id = request.body.Head.msgh_id + 100;
--- a/toolkit/recordreplay/File.cpp
+++ b/toolkit/recordreplay/File.cpp
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "File.h"
 
-#include "ipc/ChildInternal.h"
+#include "ipc/ChildIPC.h"
 #include "mozilla/Compression.h"
 #include "mozilla/Sprintf.h"
 #include "ProcessRewind.h"
 #include "SpinLock.h"
 
 #include <algorithm>
 
 namespace mozilla {
@@ -156,18 +156,17 @@ Stream::WriteScalar(size_t aValue)
 }
 
 void
 Stream::CheckInput(size_t aValue)
 {
   size_t oldValue = aValue;
   RecordOrReplayScalar(&oldValue);
   if (oldValue != aValue) {
-    child::ReportFatalError(Nothing(), "Input Mismatch: Recorded: %zu Replayed %zu\n",
-                            oldValue, aValue);
+    child::ReportFatalError("Input Mismatch: Recorded: %zu Replayed %zu\n", oldValue, aValue);
     Unreachable();
   }
 }
 
 void
 Stream::EnsureMemory(UniquePtr<char[]>* aBuf, size_t* aSize,
                      size_t aNeededSize, size_t aMaxSize, ShouldCopy aCopy)
 {
--- a/toolkit/recordreplay/MemorySnapshot.cpp
+++ b/toolkit/recordreplay/MemorySnapshot.cpp
@@ -299,17 +299,17 @@ public:
 // are in untracked memory.
 struct MemoryInfo {
   // Whether new dirty pages or allocated regions are allowed.
   bool mMemoryChangesAllowed;
 
   // Untracked memory regions allocated before the first checkpoint. This is only
   // accessed on the main thread, and is not a vector because of reentrancy
   // issues.
-  static const size_t MaxInitialUntrackedRegions = 512;
+  static const size_t MaxInitialUntrackedRegions = 256;
   AllocatedMemoryRegion mInitialUntrackedRegions[MaxInitialUntrackedRegions];
   SpinLock mInitialUntrackedRegionsLock;
 
   // All tracked memory in the process. This may be updated by any thread while
   // holding mTrackedRegionsLock.
   SplayTree<AllocatedMemoryRegion, AllocatedMemoryRegion::AddressSort,
             AllocPolicy<MemoryKind::TrackedRegions>, 4>
     mTrackedRegions;
@@ -405,17 +405,17 @@ AutoCountdown::~AutoCountdown()
 
 static void
 CountdownThreadMain(void*)
 {
   while (true) {
     if (gMemoryInfo->mCountdown && --gMemoryInfo->mCountdown == 0) {
       // When debugging hangs in the child process, we can break here in lldb
       // to inspect what the process is doing.
-      child::ReportFatalError(Nothing(), "CountdownThread activated");
+      child::ReportFatalError("CountdownThread activated");
     }
     ThreadYield();
   }
 }
 
 #endif // WANT_COUNTDOWN_THREAD
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -660,23 +660,21 @@ HandleDirtyMemoryFault(uint8_t* aAddress
   gMemoryInfo->mActiveDirty.insert(aAddress, DirtyPage(aAddress, original, executable));
   DirectUnprotectMemory(aAddress, PageSize, executable);
   return true;
 }
 
 void
 UnrecoverableSnapshotFailure()
 {
-  if (gMemoryInfo) {
-    AutoSpinLock lock(gMemoryInfo->mTrackedRegionsLock);
-    DirectUnprotectMemory(PageBase(&errno), PageSize, false);
-    for (auto region : gMemoryInfo->mTrackedRegionsByAllocationOrder) {
-      DirectUnprotectMemory(region.mBase, region.mSize, region.mExecutable,
-                            /* aIgnoreFailures = */ true);
-    }
+  AutoSpinLock lock(gMemoryInfo->mTrackedRegionsLock);
+  DirectUnprotectMemory(PageBase(&errno), PageSize, false);
+  for (auto region : gMemoryInfo->mTrackedRegionsByAllocationOrder) {
+    DirectUnprotectMemory(region.mBase, region.mSize, region.mExecutable,
+                          /* aIgnoreFailures = */ true);
   }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 // Initial Memory Region Processing
 ///////////////////////////////////////////////////////////////////////////////
 
 void
@@ -723,90 +721,23 @@ RemoveInitialUntrackedRegion(uint8_t* aB
       region.mBase = nullptr;
       region.mSize = 0;
       return;
     }
   }
   MOZ_CRASH();
 }
 
-// Get information about the mapped region containing *aAddress, or the next
-// mapped region afterwards if aAddress is not mapped. aAddress is updated to
-// the start of that region, and aSize, aProtection, and aMaxProtection are
-// updated with the size and protection status of the region. Returns false if
-// there are no more mapped regions after *aAddress.
-static bool
-QueryRegion(uint8_t** aAddress, size_t* aSize,
-            int* aProtection = nullptr, int* aMaxProtection = nullptr)
-{
-  mach_vm_address_t addr = (mach_vm_address_t) *aAddress;
-  mach_vm_size_t nbytes;
-
-  vm_region_basic_info_64 info;
-  mach_msg_type_number_t info_count = sizeof(vm_region_basic_info_64);
-  mach_port_t some_port;
-  kern_return_t rv = mach_vm_region(mach_task_self(), &addr, &nbytes, VM_REGION_BASIC_INFO,
-                                    (vm_region_info_t) &info, &info_count, &some_port);
-  if (rv == KERN_INVALID_ADDRESS) {
-    return false;
-  }
-  MOZ_RELEASE_ASSERT(rv == KERN_SUCCESS);
-
-  *aAddress = (uint8_t*) addr;
-  *aSize = nbytes;
-  if (aProtection) {
-    *aProtection = info.protection;
-  }
-  if (aMaxProtection) {
-    *aMaxProtection = info.max_protection;
-  }
-  return true;
-}
-
 static void
 MarkThreadStacksAsUntracked()
 {
-  AutoPassThroughThreadEvents pt;
-
   // Thread stacks are excluded from the tracked regions.
   for (size_t i = MainThreadId; i <= MaxThreadId; i++) {
     Thread* thread = Thread::GetById(i);
-    if (!thread->StackBase()) {
-      continue;
-    }
-
     AddInitialUntrackedMemoryRegion(thread->StackBase(), thread->StackSize());
-
-    // Look for a mapped region with no access permissions immediately after
-    // the thread stack's allocated region, and include this in the untracked
-    // memory if found. This is done to avoid confusing breakpad, which will
-    // scan the allocated memory in this process and will not correctly
-    // determine stack boundaries if we track these trailing regions and end up
-    // marking them as readable.
-
-    // Find the mapped region containing the thread's stack.
-    uint8_t* base = thread->StackBase();
-    size_t size;
-    if (!QueryRegion(&base, &size)) {
-      MOZ_CRASH("Could not find memory region information for thread stack");
-    }
-
-    // Sanity check the region size. Note that we don't mark this entire region
-    // as untracked, since it may contain TLS data which should be tracked.
-    MOZ_RELEASE_ASSERT(base <= thread->StackBase());
-    MOZ_RELEASE_ASSERT(base + size >= thread->StackBase() + thread->StackSize());
-
-    uint8_t* trailing = base + size;
-    size_t trailingSize;
-    int protection;
-    if (QueryRegion(&trailing, &trailingSize, &protection)) {
-      if (trailing == base + size && protection == 0) {
-        AddInitialUntrackedMemoryRegion(trailing, trailingSize);
-      }
-    }
   }
 }
 
 // Given an address region [*aAddress, *aAddress + *aSize], return true if
 // there is any intersection with an excluded region
 // [aExclude, aExclude + aExcludeSize], set *aSize to contain the subregion
 // starting at aAddress which which is not excluded, and *aRemaining and
 // *aRemainingSize to any additional subregion which is not excluded.
@@ -892,40 +823,44 @@ AddInitialTrackedMemoryRegions(uint8_t* 
 
     aAddress = remaining;
     aSize = remainingSize;
   }
 }
 
 static void UpdateNumTrackedRegionsForSnapshot();
 
-// Fill in the set of tracked memory regions that are currently mapped within
-// this process.
+// Handle all initial untracked memory regions in the process.
 static void
 ProcessAllInitialMemoryRegions()
 {
   MOZ_ASSERT(!AreThreadEventsPassedThrough());
 
   {
     AutoPassThroughThreadEvents pt;
-    for (uint8_t* addr = nullptr;;) {
-      size_t size;
-      int maxProtection;
-      if (!QueryRegion(&addr, &size, nullptr, &maxProtection)) {
+    for (mach_vm_address_t addr = 0;;) {
+      mach_vm_size_t nbytes;
+
+      vm_region_basic_info_64 info;
+      mach_msg_type_number_t info_count = sizeof(vm_region_basic_info_64);
+      mach_port_t some_port;
+      kern_return_t rv = mach_vm_region(mach_task_self(), &addr, &nbytes, VM_REGION_BASIC_INFO,
+                                        (vm_region_info_t) &info, &info_count, &some_port);
+      if (rv == KERN_INVALID_ADDRESS) {
         break;
       }
+      MOZ_RELEASE_ASSERT(rv == KERN_SUCCESS);
+
+      if (info.max_protection & VM_PROT_WRITE) {
+        MOZ_RELEASE_ASSERT(info.max_protection & VM_PROT_READ);
+        AddInitialTrackedMemoryRegions(reinterpret_cast<uint8_t*>(addr), nbytes,
+                                       info.max_protection & VM_PROT_EXECUTE);
+      }
 
-      // Consider all memory regions that can possibly be written to, even if
-      // they aren't currently writable.
-      if (maxProtection & VM_PROT_WRITE) {
-        MOZ_RELEASE_ASSERT(maxProtection & VM_PROT_READ);
-        AddInitialTrackedMemoryRegions(addr, size, maxProtection & VM_PROT_EXECUTE);
-      }
-
-      addr += size;
+      addr += nbytes;
     }
   }
 
   UpdateNumTrackedRegionsForSnapshot();
 
   // Write protect all tracked memory.
   AutoDisallowMemoryChanges disallow;
   for (const AllocatedMemoryRegion& region : gMemoryInfo->mTrackedRegionsByAllocationOrder) {
@@ -1124,24 +1059,24 @@ CheckFixedMemory(void* aAddress, size_t 
     // of which entirely contains this memory.
     AutoSpinLock lock(gMemoryInfo->mTrackedRegionsLock);
     for (size_t offset = 0; offset < aSize; offset += PageSize) {
       uint8_t* page = (uint8_t*)aAddress + offset;
       Maybe<AllocatedMemoryRegion> region =
         gMemoryInfo->mTrackedRegions.lookupClosestLessOrEqual(page);
       if (!region.isSome() ||
           !MemoryContains(region.ref().mBase, region.ref().mSize, page, PageSize)) {
-        MOZ_CRASH("Fixed memory is not tracked!");
+        child::ReportFatalError("Fixed memory is not tracked!");
       }
     }
   }
 
   // The memory should not be free.
   if (gFreeRegions.Intersects(aAddress, aSize)) {
-    MOZ_CRASH("Fixed memory is currently free!");
+    child::ReportFatalError("Fixed memory is currently free!");
   }
 }
 
 void
 RestoreWritableFixedMemory(void* aAddress, size_t aSize)
 {
   MOZ_RELEASE_ASSERT(aAddress == PageBase(aAddress));
   MOZ_RELEASE_ASSERT(aSize == RoundupSizeToPageBoundary(aSize));
--- a/toolkit/recordreplay/ProcessRecordReplay.cpp
+++ b/toolkit/recordreplay/ProcessRecordReplay.cpp
@@ -200,19 +200,19 @@ RecordReplayInterface_InternalRecordRepl
   thread->Events().CheckInput(aSize);
   thread->Events().RecordOrReplayBytes(aData, aSize);
 }
 
 MOZ_EXPORT void
 RecordReplayInterface_InternalInvalidateRecording(const char* aWhy)
 {
   if (IsRecording()) {
-    child::ReportFatalError(Nothing(), "Recording invalidated: %s", aWhy);
+    child::ReportFatalError("Recording invalidated: %s", aWhy);
   } else {
-    child::ReportFatalError(Nothing(), "Recording invalidated while replaying: %s", aWhy);
+    child::ReportFatalError("Recording invalidated while replaying: %s", aWhy);
   }
   Unreachable();
 }
 
 } // extern "C"
 
 // How many recording endpoints have been flushed to the recording.
 static size_t gNumEndpoints;
@@ -466,18 +466,17 @@ RecordReplayInterface_InternalRecordRepl
         }
       }
 
       {
         AutoPassThroughThreadEvents pt;
         SetCurrentStackString(text, text + strlen(text), sizeof(text) - strlen(text));
       }
 
-      child::ReportFatalError(Nothing(),
-                              "Assertion Mismatch: Thread %d\n"
+      child::ReportFatalError("Assertion Mismatch: Thread %d\n"
                               "Recorded: %s [%d,%d]\n"
                               "Replayed: %s [%d,%d]\n",
                               (int) thread->Id(), buffer, (int) streamPos, (int) progress, text,
                               (int) thread->Events().StreamPosition(),
                               (int) (thread->IsMainThread() ? *ExecutionProgressCounter() : 0));
       Unreachable();
     }
 
@@ -543,18 +542,17 @@ RecordReplayInterface_InternalRecordRepl
             }
           }
         }
         if (mismatches == MAX_MISMATCHES) {
           Print("Position ...\n");
         }
       }
 
-      child::ReportFatalError(Nothing(),
-                              "Byte Comparison Check Failed: Position %d %d Length %d %d\n",
+      child::ReportFatalError("Byte Comparison Check Failed: Position %d %d Length %d %d\n",
                               (int) streamPos, (int) thread->Events().StreamPosition(),
                               (int) oldSize, (int) aSize);
       Unreachable();
     }
 
     thread->RestoreBuffer(buffer);
   }
 #endif // INCLUDE_RECORD_REPLAY_ASSERTIONS
--- a/toolkit/recordreplay/ProcessRedirectDarwin.cpp
+++ b/toolkit/recordreplay/ProcessRedirectDarwin.cpp
@@ -145,17 +145,16 @@ namespace recordreplay {
   MACRO(mach_msg)                               \
   MACRO(mach_timebase_info)                     \
   MACRO(mach_vm_allocate)                       \
   MACRO(mach_vm_deallocate)                     \
   MACRO(mach_vm_protect)                        \
   MACRO(sandbox_free_error)                     \
   MACRO(sandbox_init)                           \
   MACRO(sandbox_init_with_parameters)           \
-  MACRO(task_threads)                           \
   MACRO(vm_copy)                                \
   MACRO(vm_purgable_control)                    \
   MACRO(tzset)                                  \
   /* NSPR functions */                          \
   MACRO(PL_NewHashTable)                        \
   MACRO(PL_HashTableDestroy)                    \
   /* Objective C functions */                   \
   MACRO(class_getClassMethod)                   \
@@ -1505,26 +1504,16 @@ RR_sandbox_init_with_parameters(const ch
 {
   // As for sandbox_init, call this function even while replaying.
   AutoEnsurePassThroughThreadEvents pt;
   return OriginalCall(sandbox_init_with_parameters, ssize_t,
                       aProfile, aFlags, aParameters, aErrorBuf);
 }
 
 static kern_return_t
-RR_task_threads(mach_port_t aTask, thread_act_array_t *aThreads,
-                mach_msg_type_number_t *aNumThreads)
-{
-  // Make sure events are passed through here so that replaying processes can
-  // inspect their own threads.
-  AutoEnsurePassThroughThreadEvents pt;
-  return OriginalCall(task_threads, kern_return_t, aTask, aThreads, aNumThreads);
-}
-
-static kern_return_t
 RR_mach_vm_allocate(vm_map_t aTarget, mach_vm_address_t* aAddress,
                     mach_vm_size_t aSize, int aFlags)
 {
   *aAddress = (mach_vm_address_t) AllocateMemory(aSize, MemoryKind::Tracked);
   return KERN_SUCCESS;
 }
 
 static kern_return_t
--- a/toolkit/recordreplay/Thread.cpp
+++ b/toolkit/recordreplay/Thread.cpp
@@ -251,17 +251,17 @@ Thread::StartThread(Callback aStart, voi
     // Look for an idle thread.
     for (id = MainThreadId + 1; id <= MaxRecordedThreadId; id++) {
       Thread* targetThread = Thread::GetById(id);
       if (!targetThread->mStart && !targetThread->mNeedsJoin) {
         break;
       }
     }
     if (id >= MaxRecordedThreadId) {
-      child::ReportFatalError(Nothing(), "Too many threads");
+      child::ReportFatalError("Too many threads");
     }
     MOZ_RELEASE_ASSERT(id <= MaxRecordedThreadId);
   }
   thread->Events().RecordOrReplayThreadEvent(ThreadEvent::CreateThread);
   thread->Events().RecordOrReplayScalar(&id);
 
   Thread* targetThread = GetById(id);
 
--- a/toolkit/recordreplay/Trigger.cpp
+++ b/toolkit/recordreplay/Trigger.cpp
@@ -183,17 +183,17 @@ RecordReplayInterface_ExecuteTriggers()
     thread->Events().RecordOrReplayThreadEvent(ThreadEvent::ExecuteTriggersFinished);
   } else {
     // Execute the same callbacks which were executed at this point while
     // recording.
     while (true) {
       ThreadEvent ev = (ThreadEvent) thread->Events().ReadScalar();
       if (ev != ThreadEvent::ExecuteTrigger) {
         if (ev != ThreadEvent::ExecuteTriggersFinished) {
-          child::ReportFatalError(Nothing(), "ExecuteTrigger Mismatch");
+          child::ReportFatalError("ExecuteTrigger Mismatch");
           Unreachable();
         }
         break;
       }
       size_t id = thread->Events().ReadScalar();
       InvokeTriggerCallback(id);
     }
   }
--- a/toolkit/recordreplay/ipc/Channel.cpp
+++ b/toolkit/recordreplay/ipc/Channel.cpp
@@ -159,23 +159,17 @@ Channel::SendMessage(const Message& aMsg
   }
 
   PrintMessage("SendMsg", aMsg);
 
   const char* ptr = (const char*) &aMsg;
   size_t nbytes = aMsg.mSize;
   while (nbytes) {
     int rv = HANDLE_EINTR(send(mFd, ptr, nbytes, 0));
-    if (rv < 0) {
-      // If the other side of the channel has crashed, don't send the message.
-      // Avoid crashing in this process too, so that we don't generate another
-      // minidump that masks the original crash.
-      MOZ_RELEASE_ASSERT(errno == EPIPE);
-      return;
-    }
+    MOZ_RELEASE_ASSERT((size_t) rv <= nbytes);
     ptr += rv;
     nbytes -= rv;
   }
 }
 
 Message*
 Channel::WaitForMessage()
 {
--- a/toolkit/recordreplay/ipc/ChildIPC.cpp
+++ b/toolkit/recordreplay/ipc/ChildIPC.cpp
@@ -9,17 +9,16 @@
 
 #include "ChildInternal.h"
 
 #include "base/message_loop.h"
 #include "base/task.h"
 #include "chrome/common/child_thread.h"
 #include "chrome/common/mach_ipc_mac.h"
 #include "ipc/Channel.h"
-#include "mac/handler/exception_handler.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/layers/ImageDataSerializer.h"
 #include "mozilla/Sprintf.h"
 #include "mozilla/VsyncDispatcher.h"
 
 #include "InfallibleVector.h"
 #include "MemorySnapshot.h"
 #include "ParentInternal.h"
@@ -278,17 +277,17 @@ InitRecordingOrReplayingProcess(int* aAr
   MOZ_RELEASE_ASSERT(*aArgc >= 1);
   MOZ_RELEASE_ASSERT(gParentArgv.back() == nullptr);
 
   *aArgc = gParentArgv.length() - 1; // For the trailing null.
   *aArgv = gParentArgv.begin();
 
   // If we failed to initialize then report it to the user.
   if (gInitializationFailureMessage) {
-    ReportFatalError(Nothing(), "%s", gInitializationFailureMessage);
+    ReportFatalError("%s", gInitializationFailureMessage);
     Unreachable();
   }
 }
 
 base::ProcessId
 MiddlemanProcessId()
 {
   return gMiddlemanPid;
@@ -296,31 +295,18 @@ MiddlemanProcessId()
 
 base::ProcessId
 ParentProcessId()
 {
   return gParentPid;
 }
 
 void
-ReportFatalError(const Maybe<MinidumpInfo>& aMinidump, const char* aFormat, ...)
+ReportFatalError(const char* aFormat, ...)
 {
-  // Unprotect any memory which might be written while producing the minidump.
-  UnrecoverableSnapshotFailure();
-
-  AutoEnsurePassThroughThreadEvents pt;
-
-#ifdef MOZ_CRASHREPORTER
-  MinidumpInfo info = aMinidump.isSome()
-                      ? aMinidump.ref()
-                      : MinidumpInfo(EXC_CRASH, 1, 0, mach_thread_self());
-  google_breakpad::ExceptionHandler::WriteForwardedExceptionMinidump
-    (info.mExceptionType, info.mCode, info.mSubcode, info.mThread);
-#endif
-
   va_list ap;
   va_start(ap, aFormat);
   char buf[2048];
   VsprintfLiteral(buf, aFormat, ap);
   va_end(ap);
 
   // Construct a FatalErrorMessage on the stack, to avoid touching the heap.
   char msgBuf[4096];
@@ -332,16 +318,18 @@ ReportFatalError(const Maybe<MinidumpInf
 
   // Don't take the message lock when sending this, to avoid touching the heap.
   gChannel->SendMessage(*msg);
 
   DirectPrint("***** Fatal Record/Replay Error *****\n");
   DirectPrint(buf);
   DirectPrint("\n");
 
+  UnrecoverableSnapshotFailure();
+
   // Block until we get a terminate message and die.
   Thread::WaitForeverNoIdle();
 }
 
 void
 NotifyFlushedRecording()
 {
   gChannel->SendMessage(RecordingFlushedMessage());
--- a/toolkit/recordreplay/ipc/ChildIPC.h
+++ b/toolkit/recordreplay/ipc/ChildIPC.h
@@ -55,16 +55,19 @@ void WaitForPaintToComplete();
 already_AddRefed<gfx::DrawTarget> DrawTargetForRemoteDrawing(LayoutDeviceIntSize aSize);
 
 // Notify the middleman that the recording was flushed.
 void NotifyFlushedRecording();
 
 // Notify the middleman about an AlwaysMarkMajorCheckpoints directive.
 void NotifyAlwaysMarkMajorCheckpoints();
 
+// Report a fatal error to the middleman process.
+void ReportFatalError(const char* aFormat, ...);
+
 // Mark a time span when the main thread is idle.
 void BeginIdleTime();
 void EndIdleTime();
 
 } // namespace child
 } // namespace recordreplay
 } // namespace mozilla
 
--- a/toolkit/recordreplay/ipc/ChildInternal.h
+++ b/toolkit/recordreplay/ipc/ChildInternal.h
@@ -73,34 +73,16 @@ void AfterCheckpoint(const CheckpointId&
 namespace child {
 
 void RespondToRequest(const js::CharBuffer& aBuffer);
 
 void HitCheckpoint(size_t aId, bool aRecordingEndpoint);
 
 void HitBreakpoint(bool aRecordingEndpoint, const uint32_t* aBreakpoints, size_t aNumBreakpoints);
 
-// Optional information about a crash that occurred. If not provided to
-// ReportFatalError, the current thread will be treated as crashed.
-struct MinidumpInfo
-{
-  int mExceptionType;
-  int mCode;
-  int mSubcode;
-  mach_port_t mThread;
-
-  MinidumpInfo(int aExceptionType, int aCode, int aSubcode, mach_port_t aThread)
-    : mExceptionType(aExceptionType), mCode(aCode), mSubcode(aSubcode), mThread(aThread)
-  {}
-};
-
-// Generate a minidump and report a fatal error to the middleman process.
-void ReportFatalError(const Maybe<MinidumpInfo>& aMinidumpInfo,
-                      const char* aFormat, ...);
-
 // Monitor used for various synchronization tasks.
 extern Monitor* gMonitor;
 
 } // namespace child
 
 } // namespace recordreplay
 } // namespace mozilla
 
--- a/toolkit/recordreplay/ipc/ChildProcess.cpp
+++ b/toolkit/recordreplay/ipc/ChildProcess.cpp
@@ -545,19 +545,19 @@ ChildProcessInfo::CanRestart()
 void
 ChildProcessInfo::AttemptRestart(const char* aWhy)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
   PrintSpew("Warning: Child process died [%d]: %s\n", (int) GetId(), aWhy);
 
   if (!CanRestart()) {
-    CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::RecordReplayError,
-                                       nsAutoCString(aWhy));
-    Shutdown();
+    nsAutoCString why(aWhy);
+    dom::ContentChild::GetSingleton()->SendRecordReplayFatalError(why);
+    Thread::WaitForeverNoIdle();
   }
 
   mNumRestarts++;
 
   dom::ContentChild::GetSingleton()->SendTerminateReplayingProcess(mChannel->GetId());
 
   bool newPaused = mPaused;
   Message* newPausedMessage = mPausedMessage;
--- a/toolkit/recordreplay/ipc/DisabledIPC.cpp
+++ b/toolkit/recordreplay/ipc/DisabledIPC.cpp
@@ -88,16 +88,22 @@ NotifyFlushedRecording()
 
 void
 NotifyAlwaysMarkMajorCheckpoints()
 {
   MOZ_CRASH();
 }
 
 void
+ReportFatalError(const char* aFormat, ...)
+{
+  MOZ_CRASH();
+}
+
+void
 BeginIdleTime()
 {
   MOZ_CRASH();
 }
 
 void
 EndIdleTime()
 {
@@ -154,18 +160,12 @@ OpenChannel(base::ProcessId aMiddlemanPi
 void
 GetArgumentsForChildProcess(base::ProcessId aMiddlemanPid, uint32_t aChannelId,
                             const char* aRecordingFile, bool aRecording,
                             std::vector<std::string>& aExtraArgs)
 {
   MOZ_CRASH();
 }
 
-base::ProcessId
-ParentProcessId()
-{
-  MOZ_CRASH();
-}
-
 } // namespace parent
 
 } // namespace recordreplay
 } // namespace mozilla
--- a/toolkit/recordreplay/ipc/ParentForwarding.cpp
+++ b/toolkit/recordreplay/ipc/ParentForwarding.cpp
@@ -317,17 +317,17 @@ public:
   }
 
   virtual void OnChannelClose() override {
     MOZ_RELEASE_ASSERT(mSide == ipc::ChildSide);
     MainThreadMessageLoop()->PostTask(NewRunnableFunction("Shutdown", Shutdown));
   }
 
   virtual void OnChannelError() override {
-    MainThreadMessageLoop()->PostTask(NewRunnableFunction("Shutdown", Shutdown));
+    MOZ_CRASH("MiddlemanProtocol::OnChannelError");
   }
 };
 
 static MiddlemanProtocol* gChildProtocol;
 static MiddlemanProtocol* gParentProtocol;
 
 ipc::MessageChannel*
 ChannelToUIProcess()
--- a/toolkit/recordreplay/ipc/ParentIPC.cpp
+++ b/toolkit/recordreplay/ipc/ParentIPC.cpp
@@ -844,33 +844,23 @@ ActiveChildTargetCheckpoint()
 static MessageLoop* gMainThreadMessageLoop;
 
 MessageLoop*
 MainThreadMessageLoop()
 {
   return gMainThreadMessageLoop;
 }
 
-static base::ProcessId gParentPid;
-
-base::ProcessId
-ParentProcessId()
-{
-  return gParentPid;
-}
-
 void
 InitializeMiddleman(int aArgc, char* aArgv[], base::ProcessId aParentPid,
                     const base::SharedMemoryHandle& aPrefsHandle,
                     const ipc::FileDescriptor& aPrefMapHandle)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
-  gParentPid = aParentPid;
-
   // Construct the message that will be sent to each child when starting up.
   IntroductionMessage* msg =
     IntroductionMessage::New(aParentPid, aArgc, aArgv);
   ChildProcessInfo::SetIntroductionMessage(msg);
 
   MOZ_RELEASE_ASSERT(gProcessKind == ProcessKind::MiddlemanRecording ||
                      gProcessKind == ProcessKind::MiddlemanReplaying);
 
--- a/toolkit/recordreplay/ipc/ParentIPC.h
+++ b/toolkit/recordreplay/ipc/ParentIPC.h
@@ -32,19 +32,16 @@ namespace parent {
 // Initialize state in a UI process.
 void InitializeUIProcess(int aArgc, char** aArgv);
 
 // Get any directory where content process recordings should be saved.
 const char* SaveAllRecordingsDirectory();
 
 // Middleman process API
 
-// Get the pid of the UI process.
-base::ProcessId ParentProcessId();
-
 // Save the recording up to the current point in execution.
 void SaveRecording(const ipc::FileDescriptor& aFile);
 
 // Get the message channel used to communicate with the UI process.
 ipc::MessageChannel* ChannelToUIProcess();
 
 // Initialize state in a middleman process.
 void InitializeMiddleman(int aArgc, char* aArgv[], base::ProcessId aParentPid,
--- a/toolkit/recordreplay/moz.build
+++ b/toolkit/recordreplay/moz.build
@@ -44,16 +44,14 @@ else:
     UNIFIED_SOURCES += [
         'ipc/DisabledIPC.cpp',
     ]
 
 LOCAL_INCLUDES += [
     '!/ipc/ipdl/_ipdlheaders',
     '/ipc/chromium/src',
     '/js/xpconnect/src',
-    '/toolkit/crashreporter/breakpad-client',
-    '/toolkit/crashreporter/google-breakpad/src',
 ]
 
 FINAL_LIBRARY = 'xul'
 
 with Files('**'):
     BUG_COMPONENT = ('Core', 'Web Replay')
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -290,17 +290,20 @@ XRE_TakeMinidumpForChild(uint32_t aChild
 bool
 #if defined(XP_WIN)
 XRE_SetRemoteExceptionHandler(const char* aPipe /*= 0*/,
                               uintptr_t aCrashTimeAnnotationFile)
 #else
 XRE_SetRemoteExceptionHandler(const char* aPipe /*= 0*/)
 #endif
 {
-  recordreplay::AutoPassThroughThreadEvents pt;
+  // Crash reporting is disabled for now when recording or replaying executions.
+  if (recordreplay::IsRecordingOrReplaying() || recordreplay::IsMiddleman()) {
+    return true;
+  }
 #if defined(XP_WIN)
   return CrashReporter::SetRemoteExceptionHandler(nsDependentCString(aPipe),
                                                   aCrashTimeAnnotationFile);
 #elif defined(XP_MACOSX)
   return CrashReporter::SetRemoteExceptionHandler(nsDependentCString(aPipe));
 #else
   return CrashReporter::SetRemoteExceptionHandler();
 #endif