Bug 1463048 - Remove asynchronous minidump generation r=ted a=pascalc
authorGabriele Svelto <gsvelto@mozilla.com>
Mon, 17 Sep 2018 20:51:45 +0000
changeset 490160 b3fad6a4c6cb3b26e1692ef9caa42e965564dc0e
parent 490159 3947b51293f6f3ddd8173b263cee69f7e4850a45
child 490161 01dd14f85e40ed9ffadb2296aa305c4c7022e99c
push id9928
push usergsvelto@mozilla.com
push dateWed, 03 Oct 2018 11:03:51 +0000
treeherdermozilla-beta@b3fad6a4c6cb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted, pascalc
bugs1463048, 1360308, 1390143, 1469603
milestone63.0
Bug 1463048 - Remove asynchronous minidump generation r=ted a=pascalc This reverts the changes in bug 1360308, bug 1390143 and bug 1469603. Minidump generation will now only happen on the main process' main thread which might lead to hangs but is known to be fairly robust. Asynchronous generation proved too brittle and enormously increased the complexity of this already hard-to-read code. Differential Revision: https://phabricator.services.mozilla.com/D5147
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/ProcessHangMonitor.cpp
dom/plugins/ipc/PluginBridge.h
dom/plugins/ipc/PluginHangUIParent.cpp
dom/plugins/ipc/PluginModuleParent.cpp
dom/plugins/ipc/PluginModuleParent.h
ipc/glue/CrashReporterHost.cpp
ipc/glue/CrashReporterHost.h
toolkit/crashreporter/nsDummyExceptionHandler.cpp
toolkit/crashreporter/nsExceptionHandler.cpp
toolkit/crashreporter/nsExceptionHandler.h
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -3375,43 +3375,26 @@ ContentParent::KillHard(const char* aRea
     // it exists and is being appended.
     nsAutoCString additionalDumps("browser");
     mCrashReporter->AddAnnotation(
       CrashReporter::Annotation::additional_minidumps, additionalDumps);
     nsDependentCString reason(aReason);
     mCrashReporter->AddAnnotation(CrashReporter::Annotation::ipc_channel_error,
                                   reason);
 
+    // Generate the report and insert into the queue for submittal.
+    if (mCrashReporter->GenerateMinidumpAndPair(this,
+                                                nullptr,
+                                                NS_LITERAL_CSTRING("browser")))
+    {
+      mCreatedPairedMinidumps = mCrashReporter->FinalizeCrashReport();
+    }
+
     Telemetry::Accumulate(Telemetry::SUBPROCESS_KILL_HARD, reason, 1);
-
-    RefPtr<ContentParent> self = this;
-    std::function<void(bool)> callback = [self](bool aResult) {
-      self->OnGenerateMinidumpComplete(aResult);
-    };
-    // Generate the report and insert into the queue for submittal.
-    mCrashReporter->GenerateMinidumpAndPair(Process(),
-                                            nullptr,
-                                            NS_LITERAL_CSTRING("browser"),
-                                            std::move(callback),
-                                            true);
-    return;
-  }
-
-  OnGenerateMinidumpComplete(false);
-}
-
-void
-ContentParent::OnGenerateMinidumpComplete(bool aDumpResult)
-{
-  if (mCrashReporter && aDumpResult) {
-    // CrashReporterHost::GenerateMinidumpAndPair() is successful.
-    mCreatedPairedMinidumps = mCrashReporter->FinalizeCrashReport();
-  }
-
-  Unused << aDumpResult; // Don't care about result if no minidump was requested.
+  }
 
   ProcessHandle otherProcessHandle;
   if (!base::OpenProcessHandle(OtherPid(), &otherProcessHandle)) {
     NS_ERROR("Failed to open child process when attempting kill.");
     return;
   }
 
   if (!KillProcess(otherProcessHandle, base::PROCESS_END_KILLED_BY_USER,
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -857,18 +857,16 @@ private:
 
   // Perform any steps necesssary to gracefully shtudown the message
   // manager and null out mMessageManager.
   void ShutDownMessageManager();
 
   // Start the force-kill timer on shutdown.
   void StartForceKillTimer();
 
-  void OnGenerateMinidumpComplete(bool aDumpResult);
-
   // Ensure that the permissions for the giben Permission key are set in the
   // content process.
   //
   // See nsIPermissionManager::GetPermissionsForKey for more information on
   // these keys.
   void EnsurePermissionsByKey(const nsCString& aKey);
 
   static void ForceKillTimerCallback(nsITimer* aTimer, void* aClosure);
--- a/dom/ipc/ProcessHangMonitor.cpp
+++ b/dom/ipc/ProcessHangMonitor.cpp
@@ -259,18 +259,16 @@ public:
   bool IsOnThread() { return mHangMonitor->IsOnThread(); }
 
 private:
   bool TakeBrowserMinidump(const PluginHangData& aPhd, nsString& aCrashId);
 
   void SendHangNotification(const HangData& aHangData,
                             const nsString& aBrowserDumpId,
                             bool aTakeMinidump);
-  void OnTakeFullMinidumpComplete(const HangData& aHangData,
-                                  const nsString& aDumpId);
 
   void ClearHangNotification();
 
   void PaintWhileInterruptingJSOnThread(TabId aTabId, bool aForceRepaint, const LayersObserverEpoch& aEpoch);
 
   void ShutdownOnThread();
 
   const RefPtr<ProcessHangMonitor> mHangMonitor;
@@ -733,58 +731,35 @@ HangMonitorParent::Bind(Endpoint<PProces
 void
 HangMonitorParent::SendHangNotification(const HangData& aHangData,
                                         const nsString& aBrowserDumpId,
                                         bool aTakeMinidump)
 {
   // chrome process, main thread
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
+  nsString dumpId;
   if ((aHangData.type() == HangData::TPluginHangData) && aTakeMinidump) {
     // We've been handed a partial minidump; complete it with plugin and
     // content process dumps.
     const PluginHangData& phd = aHangData.get_PluginHangData();
 
-    WeakPtr<HangMonitorParent> self = this;
-    std::function<void(nsString)> callback =
-      [self, aHangData](nsString aResult) {
-        MOZ_RELEASE_ASSERT(NS_IsMainThread());
-
-        if (!self) {
-          // Don't report hang since the process has already shut down.
-          return;
-        }
-
-        self->UpdateMinidump(aHangData.get_PluginHangData().pluginId(),
-                       aResult);
-        self->OnTakeFullMinidumpComplete(aHangData, aResult);
-      };
-
-    plugins::TakeFullMinidump(phd.pluginId(),
-                              phd.contentProcessId(),
-                              aBrowserDumpId,
-                              std::move(callback),
-                              true);
+    plugins::TakeFullMinidump(phd.pluginId(), phd.contentProcessId(),
+                              aBrowserDumpId, dumpId);
+    UpdateMinidump(phd.pluginId(), dumpId);
   } else {
     // We already have a full minidump; go ahead and use it.
-    OnTakeFullMinidumpComplete(aHangData, aBrowserDumpId);
+    dumpId = aBrowserDumpId;
   }
-}
 
-void
-HangMonitorParent::OnTakeFullMinidumpComplete(const HangData& aHangData,
-                                              const nsString& aDumpId)
-{
-  mProcess->SetHangData(aHangData, aDumpId);
+  mProcess->SetHangData(aHangData, dumpId);
 
   nsCOMPtr<nsIObserverService> observerService =
     mozilla::services::GetObserverService();
-  observerService->NotifyObservers(mProcess,
-                                   "process-hang-report",
-                                   nullptr);
+  observerService->NotifyObservers(mProcess, "process-hang-report", nullptr);
 }
 
 void
 HangMonitorParent::ClearHangNotification()
 {
   // chrome process, main thread
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   mProcess->ClearHang();
@@ -1112,30 +1087,22 @@ HangMonitoredProcess::TerminatePlugin()
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   if (mHangData.type() != HangData::TPluginHangData) {
     return NS_ERROR_UNEXPECTED;
   }
 
   // Use the multi-process crash report generated earlier.
   uint32_t id = mHangData.get_PluginHangData().pluginId();
   base::ProcessId contentPid = mHangData.get_PluginHangData().contentProcessId();
+  plugins::TerminatePlugin(id, contentPid, NS_LITERAL_CSTRING("HangMonitor"),
+                           mDumpId);
 
-  RefPtr<HangMonitoredProcess> self{this};
-  std::function<void(bool)> callback =
-    [self, id](bool aResult) {
-      if (self->mActor) {
-        self->mActor->CleanupPluginHang(id, false);
-      }
-    };
-
-  plugins::TerminatePlugin(id,
-                           contentPid,
-                           NS_LITERAL_CSTRING("HangMonitor"),
-                           mDumpId,
-                           std::move(callback));
+  if (mActor) {
+    mActor->CleanupPluginHang(id, false);
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 HangMonitoredProcess::IsReportForBrowser(nsFrameLoader* aFrameLoader, bool* aResult)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
--- a/dom/plugins/ipc/PluginBridge.h
+++ b/dom/plugins/ipc/PluginBridge.h
@@ -2,18 +2,16 @@
  * vim: sw=2 ts=2 et :
  * 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/. */
 
 #ifndef mozilla_plugins_PluginBridge_h
 #define mozilla_plugins_PluginBridge_h
 
-#include <functional>
-
 #include "base/process.h"
 
 namespace mozilla {
 
 namespace dom {
 class ContentParent;
 } // namespace dom
 
@@ -36,21 +34,20 @@ FindPluginsForContent(uint32_t aPluginEp
                       nsTArray<PluginTag>* aPlugins,
                       nsTArray<FakePluginTag>* aFakePlugins,
                       uint32_t* aNewPluginEpoch);
 
 void
 TakeFullMinidump(uint32_t aPluginId,
                  base::ProcessId aContentProcessId,
                  const nsAString& aBrowserDumpId,
-                 std::function<void(nsString)>&& aCallback,
-                 bool aAsync);
+                 nsString& aDumpId);
 
 void
 TerminatePlugin(uint32_t aPluginId,
                 base::ProcessId aContentProcessId,
                 const nsCString& aMonitorDescription,
-                const nsAString& aDumpId,
-                std::function<void(bool)>&& aCallback);
+                const nsAString& aDumpId);
+
 } // namespace plugins
 } // namespace mozilla
 
 #endif // mozilla_plugins_PluginBridge_h
--- a/dom/plugins/ipc/PluginHangUIParent.cpp
+++ b/dom/plugins/ipc/PluginHangUIParent.cpp
@@ -350,23 +350,20 @@ PluginHangUIParent::RecvUserResponse(con
   }
   mLastUserResponse = aResponse;
   mResponseTicks = ::GetTickCount();
   mIsShowing = false;
   // responseCode: 1 = Stop, 2 = Continue, 3 = Cancel
   int responseCode;
   if (aResponse & HANGUI_USER_RESPONSE_STOP) {
     // User clicked Stop
-    std::function<void(bool)> callback = [](bool aResult) { };
     mModule->TerminateChildProcess(mMainThreadMessageLoop,
                                    mozilla::ipc::kInvalidProcessId,
                                    NS_LITERAL_CSTRING("ModalHangUI"),
-                                   EmptyString(),
-                                   mModule->DummyCallback<bool>(),
-                                   /* aAsync = */ false);
+                                   EmptyString());
     responseCode = 1;
   } else if(aResponse & HANGUI_USER_RESPONSE_CONTINUE) {
     mModule->OnHangUIContinue();
     // User clicked Continue
     responseCode = 2;
   } else {
     // Dialog was cancelled
     responseCode = 3;
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -352,51 +352,40 @@ PluginModuleChromeParentForId(const uint
 
   return static_cast<PluginModuleChromeParent*>(plugin->GetLibrary());
 }
 
 void
 mozilla::plugins::TakeFullMinidump(uint32_t aPluginId,
                                    base::ProcessId aContentProcessId,
                                    const nsAString& aBrowserDumpId,
-                                   std::function<void(nsString)>&& aCallback,
-                                   bool aAsync)
+                                   nsString& aDumpId)
 {
   PluginModuleChromeParent* chromeParent =
     PluginModuleChromeParentForId(aPluginId);
 
   if (chromeParent) {
-    chromeParent->TakeFullMinidump(aContentProcessId,
-                                   aBrowserDumpId,
-                                   std::move(aCallback),
-                                   aAsync);
-  } else {
-    aCallback(EmptyString());
+    chromeParent->TakeFullMinidump(aContentProcessId, aBrowserDumpId, aDumpId);
   }
 }
 
 void
 mozilla::plugins::TerminatePlugin(uint32_t aPluginId,
                                   base::ProcessId aContentProcessId,
                                   const nsCString& aMonitorDescription,
-                                  const nsAString& aDumpId,
-                                  std::function<void(bool)>&& aCallback)
+                                  const nsAString& aDumpId)
 {
   PluginModuleChromeParent* chromeParent =
     PluginModuleChromeParentForId(aPluginId);
 
   if (chromeParent) {
     chromeParent->TerminateChildProcess(MessageLoop::current(),
                                         aContentProcessId,
                                         aMonitorDescription,
-                                        aDumpId,
-                                        std::move(aCallback),
-                                        true); // Always runs asynchronously.
-  } else {
-    aCallback(true);
+                                        aDumpId);
   }
 }
 
 /* static */ PluginLibrary*
 PluginModuleContentParent::LoadModule(uint32_t aPluginId,
                                       nsPluginTag* aPluginTag)
 {
     PluginModuleMapping::NotifyLoadingModule loadingModule;
@@ -582,17 +571,17 @@ PluginModuleChromeParent::InitCrashRepor
     }
 
     NativeThreadId threadId;
     if (!CallInitCrashReporter(shmem, &threadId)) {
         return false;
     }
 
     {
-      mozilla::RecursiveMutexAutoLock lock(mCrashReporterMutex);
+      mozilla::MutexAutoLock lock(mCrashReporterMutex);
       mCrashReporter = MakeUnique<ipc::CrashReporterHost>(
         GeckoProcessType_Plugin,
         shmem,
         threadId);
     }
 
     return true;
 }
@@ -722,17 +711,17 @@ PluginModuleChromeParent::~PluginModuleC
 
     mozilla::BackgroundHangMonitor::UnregisterAnnotator(*this);
 }
 
 void
 PluginModuleChromeParent::WriteExtraDataForMinidump()
 {
     // mCrashReporterMutex is already held by the caller
-    mCrashReporterMutex.AssertCurrentThreadIn();
+    mCrashReporterMutex.AssertCurrentThreadOwns();
 
     typedef nsDependentCString cstring;
 
     // Get the plugin filename, try to get just the file leafname
     const std::string& pluginFile = mSubprocess->GetPluginFilePath();
     size_t filePos = pluginFile.rfind(FILE_PATH_SEPARATOR);
     if (filePos == std::string::npos)
         filePos = 0;
@@ -1061,24 +1050,20 @@ PluginModuleChromeParent::ShouldContinue
     if (LaunchHangUI()) {
         return true;
     }
     // If LaunchHangUI returned false then we should proceed with the
     // original plugin hang behaviour and kill the plugin container.
     FinishHangUI();
 #endif // XP_WIN
 
-    // Terminate the child process synchronously because this function can be
-    // called in sync IPC.
     TerminateChildProcess(MessageLoop::current(),
                           mozilla::ipc::kInvalidProcessId,
                           NS_LITERAL_CSTRING("ModalHangUI"),
-                          EmptyString(),
-                          DummyCallback<bool>(),
-                          /* aAsync = */ false);
+                          EmptyString());
     GetIPCChannel()->CloseWithTimeout();
     return false;
 }
 
 bool
 PluginModuleContentParent::ShouldContinueFromReplyTimeout()
 {
     RefPtr<ProcessHangMonitor> monitor = ProcessHangMonitor::Get();
@@ -1093,151 +1078,65 @@ void
 PluginModuleContentParent::OnExitedSyncSend()
 {
     ProcessHangMonitor::ClearHang();
 }
 
 void
 PluginModuleChromeParent::TakeFullMinidump(base::ProcessId aContentPid,
                                            const nsAString& aBrowserDumpId,
-                                           std::function<void(nsString)>&& aCallback,
-                                           bool aAsync)
+                                           nsString& aDumpId)
 {
-    mozilla::RecursiveMutexAutoLock lock(mCrashReporterMutex);
-
-    if (!mCrashReporter || !mTakeFullMinidumpCallback.IsEmpty()) {
-        aCallback(EmptyString());
+    mozilla::MutexAutoLock lock(mCrashReporterMutex);
+
+    if (!mCrashReporter) {
         return;
     }
-    mTakeFullMinidumpCallback.Init(std::move(aCallback), aAsync);
-
-    nsString browserDumpId{aBrowserDumpId};
+
+    bool reportsReady = false;
 
     // Check to see if we already have a browser dump id - with e10s plugin
     // hangs we take this earlier (see ProcessHangMonitor) from a background
     // thread. We do this before we message the main thread about the hang
     // since the posted message will trash our browser stack state.
+    nsCOMPtr<nsIFile> browserDumpFile;
     if (CrashReporter::GetMinidumpForID(aBrowserDumpId,
-                                        getter_AddRefs(mBrowserDumpFile))) {
-
-        // Hold a ref to mPlugin to keep *this* alive until the callback runs.
-        RetainPluginRef();
-        std::function<void(bool)> callback =
-            [this, aContentPid, browserDumpId, aAsync](bool aResult) {
-                if (aAsync) {
-                    this->mCrashReporterMutex.Lock();
-                }
-
-                this->TakeBrowserAndPluginMinidumps(aResult,
-                                                    aContentPid,
-                                                    browserDumpId,
-                                                    aAsync);
-                if (aAsync) {
-                    this->mCrashReporterMutex.Unlock();
-                }
-
-                this->ReleasePluginRef();
-             };
+                                        getter_AddRefs(browserDumpFile))) {
         // We have a single browser report, generate a new plugin process parent
         // report and pair it up with the browser report handed in.
-        mCrashReporter->GenerateMinidumpAndPair(Process(), mBrowserDumpFile,
-                                                NS_LITERAL_CSTRING("browser"),
-                                                std::move(callback), aAsync);
-    } else {
-        TakeBrowserAndPluginMinidumps(false, aContentPid, browserDumpId, aAsync);
-    }
-}
-
-void
-PluginModuleChromeParent::RetainPluginRef()
-{
-    if (!mPlugin) {
-        return;
-    }
-
-    if (NS_IsMainThread()) {
-        mPlugin->AddRef();
-    } else {
-        // XXX We can't sync-dispatch to the main thread because doing that
-        // deadlocks when we are called from
-        // PluginHangUIParent::RecvUserResponse().
-        Unused << NS_DispatchToMainThread(
-            NewNonOwningRunnableMethod("nsNPAPIPlugin::AddRef",
-                                       mPlugin, &nsNPAPIPlugin::AddRef));
+        reportsReady = mCrashReporter->GenerateMinidumpAndPair(
+          this,
+          browserDumpFile,
+          NS_LITERAL_CSTRING("browser"));
+
+        if (!reportsReady) {
+          browserDumpFile = nullptr;
+          CrashReporter::DeleteMinidumpFilesForID(aBrowserDumpId);
+        }
     }
-}
-
-void
-PluginModuleChromeParent::ReleasePluginRef()
-{
-    if (!mPlugin) {
-        return;
-    }
-
-    if (NS_IsMainThread()) {
-        mPlugin->Release();
-    } else {
-        // Async release the reference to mPlugin.
-        Unused << NS_DispatchToMainThread(
-            NewNonOwningRunnableMethod("nsNPAPIPlugin::Release",
-                                       mPlugin, &nsNPAPIPlugin::Release));
-    }
-}
-
-void
-PluginModuleChromeParent::TakeBrowserAndPluginMinidumps(bool aReportsReady,
-                                                        base::ProcessId aContentPid,
-                                                        const nsAString& aBrowserDumpId,
-                                                        bool aAsync)
-{
-    mCrashReporterMutex.AssertCurrentThreadIn();
 
     // Generate crash report including plugin and browser process minidumps.
     // The plugin process is the parent report with additional dumps including
     // the browser process, content process when running under e10s, and
     // various flash subprocesses if we're the flash module.
-    if (!aReportsReady) {
-        mBrowserDumpFile = nullptr;
-        CrashReporter::DeleteMinidumpFilesForID(aBrowserDumpId);
-
-        nsString browserDumpId{aBrowserDumpId};
-
-        RetainPluginRef();
-        std::function<void(bool)> callback =
-            [this, aContentPid, browserDumpId](bool aResult) {
-                this->OnTakeFullMinidumpComplete(aResult,
-                                                 aContentPid,
-                                                 browserDumpId);
-                this->ReleasePluginRef();
-            };
-        mCrashReporter->GenerateMinidumpAndPair(Process(),
-                                                nullptr, // Pair with a dump of this process and thread.
-                                                NS_LITERAL_CSTRING("browser"),
-                                                std::move(callback),
-                                                aAsync);
-    } else {
-        OnTakeFullMinidumpComplete(aReportsReady, aContentPid, aBrowserDumpId);
+    if (!reportsReady) {
+        reportsReady = mCrashReporter->GenerateMinidumpAndPair(
+          this,
+          nullptr, // Pair with a dump of this process and thread.
+          NS_LITERAL_CSTRING("browser"));
     }
-}
-
-void
-PluginModuleChromeParent::OnTakeFullMinidumpComplete(bool aReportsReady,
-                                                     base::ProcessId aContentPid,
-                                                     const nsAString& aBrowserDumpId)
-{
-    mCrashReporterMutex.AssertCurrentThreadIn();
-
-    if (aReportsReady) {
-        nsString dumpId = mCrashReporter->MinidumpID();
+
+    if (reportsReady) {
+        aDumpId = mCrashReporter->MinidumpID();
         PLUGIN_LOG_DEBUG(
-                         ("generated paired browser/plugin minidumps: %s)",
-                          NS_ConvertUTF16toUTF8(dumpId).get()));
+                ("generated paired browser/plugin minidumps: %s)",
+                 NS_ConvertUTF16toUTF8(aDumpId).get()));
         nsAutoCString additionalDumps("browser");
         nsCOMPtr<nsIFile> pluginDumpFile;
-        if (GetMinidumpForID(dumpId, getter_AddRefs(pluginDumpFile))) {
+        if (GetMinidumpForID(aDumpId, getter_AddRefs(pluginDumpFile))) {
 #ifdef MOZ_CRASHREPORTER_INJECTOR
             // If we have handles to the flash sandbox processes on Windows,
             // include those minidumps as well.
             if (CreatePluginMinidump(mFlashProcess1, 0, pluginDumpFile,
                                      NS_LITERAL_CSTRING("flash1"))) {
                 additionalDumps.AppendLiteral(",flash1");
             }
             if (CreatePluginMinidump(mFlashProcess2, 0, pluginDumpFile,
@@ -1251,74 +1150,39 @@ PluginModuleChromeParent::OnTakeFullMini
                                          pluginDumpFile,
                                          NS_LITERAL_CSTRING("content"))) {
                     additionalDumps.AppendLiteral(",content");
                 }
             }
         }
         mCrashReporter->AddAnnotation(Annotation::additional_minidumps,
                                       additionalDumps);
-
-        mTakeFullMinidumpCallback.Invoke(mCrashReporter->MinidumpID());
     } else {
-        mTakeFullMinidumpCallback.Invoke(EmptyString());
         NS_WARNING("failed to capture paired minidumps from hang");
     }
 }
 
 void
 PluginModuleChromeParent::TerminateChildProcess(MessageLoop* aMsgLoop,
                                                 base::ProcessId aContentPid,
                                                 const nsCString& aMonitorDescription,
-                                                const nsAString& aDumpId,
-                                                std::function<void(bool)>&& aCallback,
-                                                bool aAsync)
+                                                const nsAString& aDumpId)
 {
-    if (!mTerminateChildProcessCallback.IsEmpty()) {
-        aCallback(false);
-        return;
-    }
-    mTerminateChildProcessCallback.Init(std::move(aCallback), aAsync);
-
     // Start by taking a full minidump if necessary, this is done early
     // because it also needs to lock the mCrashReporterMutex and Mutex doesn't
     // support recursive locking.
+    nsAutoString dumpId;
     if (aDumpId.IsEmpty()) {
-
-      RetainPluginRef();
-      std::function<void(nsString)> callback =
-            [this, aMsgLoop, aMonitorDescription, aAsync](nsString aResult) {
-                if (aAsync) {
-                    this->mCrashReporterMutex.Lock();
-                }
-                this->TerminateChildProcessOnDumpComplete(aMsgLoop,
-                                                          aMonitorDescription);
-                if (aAsync) {
-                    this->mCrashReporterMutex.Unlock();
-                }
-
-                this->ReleasePluginRef();
-            };
-
-        TakeFullMinidump(aContentPid, EmptyString(), std::move(callback), aAsync);
-    } else {
-        TerminateChildProcessOnDumpComplete(aMsgLoop, aMonitorDescription);
+        TakeFullMinidump(aContentPid, EmptyString(), dumpId);
     }
-}
-
-void
-PluginModuleChromeParent::TerminateChildProcessOnDumpComplete(MessageLoop* aMsgLoop,
-                                                              const nsCString& aMonitorDescription)
-{
-    mCrashReporterMutex.AssertCurrentThreadIn();
-
+
+    mozilla::MutexAutoLock lock(mCrashReporterMutex);
     if (!mCrashReporter) {
         // If mCrashReporter is null then the hang has ended, the plugin module
         // is shutting down. There's nothing to do here.
-        mTerminateChildProcessCallback.Invoke(true);
         return;
     }
     mCrashReporter->AddAnnotation(Annotation::PluginHang, true);
     mCrashReporter->AddAnnotation(Annotation::HangMonitorDescription,
                                   aMonitorDescription);
 #ifdef XP_WIN
     if (mHangUIParent) {
         unsigned int hangUIDuration = mHangUIParent->LastShowDurationMs();
@@ -1365,18 +1229,16 @@ PluginModuleChromeParent::TerminateChild
     bool isFromHangUI = aMsgLoop != MessageLoop::current();
     aMsgLoop->PostTask(
         mChromeTaskFactory.NewRunnableMethod(
             &PluginModuleChromeParent::CleanupFromTimeout, isFromHangUI));
 
     if (!childOpened || !KillProcess(geckoChildProcess, 1, false)) {
         NS_WARNING("failed to kill subprocess!");
     }
-
-    mTerminateChildProcessCallback.Invoke(true);
 }
 
 bool
 PluginModuleParent::GetPluginDetails()
 {
     RefPtr<nsPluginHost> host = nsPluginHost::GetInst();
     if (!host) {
         return false;
@@ -1517,17 +1379,17 @@ RemoveMinidump(nsIFile* minidump)
         extraFile->Remove(true);
     }
 }
 #endif // MOZ_CRASHREPORTER_INJECTOR
 
 void
 PluginModuleChromeParent::ProcessFirstMinidump()
 {
-    mozilla::RecursiveMutexAutoLock lock(mCrashReporterMutex);
+    mozilla::MutexAutoLock lock(mCrashReporterMutex);
 
     if (!mCrashReporter)
         return;
 
     WriteExtraDataForMinidump();
 
     if (mCrashReporter->HasMinidump()) {
         // A minidump may be set in TerminateChildProcess, which means the
--- a/dom/plugins/ipc/PluginModuleParent.h
+++ b/dom/plugins/ipc/PluginModuleParent.h
@@ -6,39 +6,40 @@
 
 #ifndef mozilla_plugins_PluginModuleParent_h
 #define mozilla_plugins_PluginModuleParent_h
 
 #include "base/process.h"
 #include "mozilla/FileUtils.h"
 #include "mozilla/HangAnnotations.h"
 #include "mozilla/PluginLibrary.h"
-#include "mozilla/ipc/CrashReporterHost.h"
 #include "mozilla/plugins/PluginProcessParent.h"
 #include "mozilla/plugins/PPluginModuleParent.h"
 #include "mozilla/plugins/PluginMessageUtils.h"
 #include "mozilla/plugins/PluginTypes.h"
 #include "mozilla/ipc/TaskFactory.h"
-#include "mozilla/RecursiveMutex.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Unused.h"
 #include "npapi.h"
 #include "npfunctions.h"
 #include "nsExceptionHandler.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "nsIObserver.h"
 #ifdef XP_WIN
 #include "nsWindowsHelpers.h"
 #endif
 
 class nsPluginTag;
 
 namespace mozilla {
 
+namespace ipc {
+class CrashReporterHost;
+} // namespace ipc
 namespace layers {
 class TextureClientRecycleAllocator;
 } // namespace layers
 
 namespace plugins {
 //-----------------------------------------------------------------------------
 
 class BrowserStreamParent;
@@ -313,21 +314,19 @@ protected:
 
     RefPtr<layers::TextureClientRecycleAllocator> mTextureAllocatorForDirectBitmap;
     RefPtr<layers::TextureClientRecycleAllocator> mTextureAllocatorForDXGISurface;
 
     /**
      * This mutex protects the crash reporter when the Plugin Hang UI event
      * handler is executing off main thread. It is intended to protect both
      * the mCrashReporter variable in addition to the CrashReporterHost object
-     * that mCrashReporter refers to. Sometimes asynchronous crash reporter
-     * callbacks are dispatched synchronously while the caller is still holding
-     * the mutex. This requires recursive locking support in the mutex.
+     * that mCrashReporter refers to.
      */
-    mozilla::RecursiveMutex mCrashReporterMutex;
+    mozilla::Mutex mCrashReporterMutex;
     UniquePtr<ipc::CrashReporterHost> mCrashReporter;
 };
 
 class PluginModuleContentParent : public PluginModuleParent
 {
   public:
     explicit PluginModuleContentParent();
 
@@ -354,20 +353,16 @@ class PluginModuleContentParent : public
     uint32_t mPluginId;
 };
 
 class PluginModuleChromeParent
     : public PluginModuleParent
     , public mozilla::BackgroundHangAnnotator
 {
     friend class mozilla::ipc::CrashReporterHost;
-    using TerminateChildProcessCallback =
-        mozilla::ipc::CrashReporterHost::CallbackWrapper<bool>;
-    using TakeFullMinidumpCallback =
-        mozilla::ipc::CrashReporterHost::CallbackWrapper<nsString>;
   public:
     /**
      * LoadModule
      *
      * This may or may not launch a plugin child process,
      * and may or may not be very expensive.
      */
     static PluginLibrary* LoadModule(const char* aFilePath, uint32_t aPluginId,
@@ -382,26 +377,22 @@ class PluginModuleChromeParent
      * Takes ownership of the file associated with aBrowserDumpId.
      *
      * @param aContentPid PID of the e10s content process from which a hang was
      *   reported. May be kInvalidProcessId if not applicable.
      * @param aBrowserDumpId (optional) previously taken browser dump id. If
      *   provided TakeFullMinidump will use this dump file instead of
      *   generating a new one. If not provided a browser dump will be taken at
      *   the time of this call.
-     * @param aCallback a callback invoked when the operation completes. The ID
-     *   of the newly generated crash dump is provided in the callback argument.
-     *   An empty string will be provided upon failure.
-     * @param aAsync whether to perform the dump asynchronously.
+     * @param aDumpId Returns the ID of the newly generated crash dump. Left
+     *   untouched upon failure.
      */
-    void
-    TakeFullMinidump(base::ProcessId aContentPid,
-                     const nsAString& aBrowserDumpId,
-                     std::function<void(nsString)>&& aCallback,
-                     bool aAsync);
+    void TakeFullMinidump(base::ProcessId aContentPid,
+                          const nsAString& aBrowserDumpId,
+                          nsString& aDumpId);
 
     /*
      * Terminates the plugin process associated with this plugin module. Also
      * generates appropriate crash reports unless an existing one is provided.
      * Takes ownership of the file associated with aDumpId on success.
      *
      * @param aMsgLoop the main message pump associated with the module
      *   protocol.
@@ -409,56 +400,21 @@ class PluginModuleChromeParent
      *   reported. May be kInvalidProcessId if not applicable.
      * @param aMonitorDescription a string describing the hang monitor that
      *   is making this call. This string is added to the crash reporter
      *   annotations for the plugin process.
      * @param aDumpId (optional) previously taken dump id. If provided
      *   TerminateChildProcess will use this dump file instead of generating a
      *   multi-process crash report. If not provided a multi-process dump will
      *   be taken at the time of this call.
-     * @param aCallback a callback invoked when the operation completes. The
-     *   argument denotes whether the operation succeeded.
-     * @param aAsync whether to perform the operation asynchronously.
      */
-    void
-    TerminateChildProcess(MessageLoop* aMsgLoop,
-                          base::ProcessId aContentPid,
-                          const nsCString& aMonitorDescription,
-                          const nsAString& aDumpId,
-                          std::function<void(bool)>&& aCallback,
-                          bool aAsync);
-
-    /**
-     * Helper for passing a dummy callback in calling the above function if it
-     * is called synchronously and the caller doesn't care about the callback
-     * result.
-     */
-    template<typename T>
-    static std::function<void(T)> DummyCallback()
-    {
-        return std::function<void(T)>([](T aResult) { });
-    }
-
-  private:
-    // The following methods are callbacks invoked after calling
-    // TakeFullMinidump(). The methods are invoked in the following order:
-    void TakeBrowserAndPluginMinidumps(bool aReportsReady,
-                                       base::ProcessId aContentPid,
-                                       const nsAString& aBrowserDumpId,
-                                       bool aAsync);
-    void OnTakeFullMinidumpComplete(bool aReportsReady,
-                                    base::ProcessId aContentPid,
-                                    const nsAString& aBrowserDumpId);
-
-
-    // The following method is the callback invoked after calling
-    // TerminateChidlProcess().
-    void TerminateChildProcessOnDumpComplete(MessageLoop* aMsgLoop,
-                                             const nsCString& aMonitorDescription);
-  public:
+    void TerminateChildProcess(MessageLoop* aMsgLoop,
+                               base::ProcessId aContentPid,
+                               const nsCString& aMonitorDescription,
+                               const nsAString& aDumpId);
 
 #ifdef XP_WIN
     /**
      * Called by Plugin Hang UI to notify that the user has clicked continue.
      * Used for chrome hang annotations.
      */
     void
     OnHangUIContinue();
@@ -481,18 +437,16 @@ private:
 
     virtual void
     AnnotateHang(mozilla::BackgroundHangAnnotations& aAnnotations) override;
 
     virtual bool ShouldContinueFromReplyTimeout() override;
 
     void ProcessFirstMinidump();
     void WriteExtraDataForMinidump();
-    void RetainPluginRef();
-    void ReleasePluginRef();
 
     PluginProcessParent* Process() const { return mSubprocess; }
     base::ProcessHandle ChildProcessHandle() { return mSubprocess->GetChildProcessHandle(); }
 
 #if defined(XP_UNIX) && !defined(XP_MACOSX)
     virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error) override;
 #else
     virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error) override;
@@ -598,21 +552,15 @@ private:
     private:
         PluginModuleChromeParent* mModule;
     };
 
     friend class LaunchedTask;
 
     nsCOMPtr<nsIObserver> mPluginOfflineObserver;
     bool mIsBlocklisted;
-
-    nsCOMPtr<nsIFile> mBrowserDumpFile;
-    TakeFullMinidumpCallback mTakeFullMinidumpCallback;
-
-    TerminateChildProcessCallback mTerminateChildProcessCallback;
-
     bool mIsCleaningFromTimeout;
 };
 
 } // namespace plugins
 } // namespace mozilla
 
 #endif // mozilla_plugins_PluginModuleParent_h
--- a/ipc/glue/CrashReporterHost.cpp
+++ b/ipc/glue/CrashReporterHost.cpp
@@ -2,31 +2,29 @@
 /* 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 "CrashReporterHost.h"
 #include "CrashReporterMetadataShmem.h"
 #include "mozilla/dom/Promise.h"
-#include "mozilla/ipc/GeckoChildProcessHost.h"
 #include "mozilla/recordreplay/ParentIPC.h"
 #include "mozilla/Sprintf.h"
 #include "mozilla/SyncRunnable.h"
 #include "mozilla/Telemetry.h"
-#include "nsExceptionHandler.h"
 #include "nsIAsyncShutdown.h"
 #include "nsICrashService.h"
 
 namespace mozilla {
 namespace ipc {
 
 CrashReporterHost::CrashReporterHost(GeckoProcessType aProcessType,
                                      const Shmem& aShmem,
-                                     ThreadId aThreadId)
+                                     CrashReporter::ThreadId aThreadId)
  : mProcessType(aProcessType),
    mShmem(aShmem),
    mThreadId(aThreadId),
    mStartTime(::time(nullptr)),
    mFinalized(false)
 {
 }
 
@@ -116,130 +114,16 @@ CrashReporterHost::FinalizeCrashReport()
 
   int32_t crashType = GetCrashType(annotations);
   NotifyCrashService(mProcessType, crashType, mDumpID);
 
   mFinalized = true;
   return true;
 }
 
-namespace {
-class GenerateMinidumpShutdownBlocker : public nsIAsyncShutdownBlocker {
-public:
-  GenerateMinidumpShutdownBlocker() = default;
-
-  NS_IMETHOD BlockShutdown(nsIAsyncShutdownClient* aBarrierClient) override
-  {
-    return NS_OK;
-  }
-
-  NS_IMETHOD GetName(nsAString& aName) override
-  {
-    aName = NS_LITERAL_STRING("Crash Reporter: blocking on minidump"
-                              "generation.");
-    return NS_OK;
-  }
-
-  NS_IMETHOD GetState(nsIPropertyBag**) override
-  {
-    return NS_OK;
-  }
-
-  NS_DECL_THREADSAFE_ISUPPORTS
-
-private:
-  virtual ~GenerateMinidumpShutdownBlocker() = default;
-};
-
-NS_IMPL_ISUPPORTS(GenerateMinidumpShutdownBlocker, nsIAsyncShutdownBlocker)
-}
-
-static nsCOMPtr<nsIAsyncShutdownClient> GetShutdownBarrier()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  nsCOMPtr<nsIAsyncShutdownService> svc = services::GetAsyncShutdown();
-  nsCOMPtr<nsIAsyncShutdownClient> barrier;
-  nsresult rv = svc->GetProfileBeforeChange(getter_AddRefs(barrier));
-
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return nullptr;
-  }
-
-  return barrier.forget();
-}
-
-void
-CrashReporterHost::GenerateMinidumpAndPair(GeckoChildProcessHost* aChildProcess,
-                                           nsIFile* aMinidumpToPair,
-                                           const nsACString& aPairName,
-                                           std::function<void(bool)>&& aCallback,
-                                           bool aAsync)
-{
-  base::ProcessHandle childHandle;
-#ifdef XP_MACOSX
-  childHandle = aChildProcess->GetChildTask();
-#else
-  childHandle = aChildProcess->GetChildProcessHandle();
-#endif
-
-  if (!mCreateMinidumpCallback.IsEmpty()) {
-    aCallback(false);
-    return;
-  }
-  mCreateMinidumpCallback.Init(std::move(aCallback), aAsync);
-
-  if (!childHandle) {
-    NS_WARNING("Failed to get child process handle.");
-    mCreateMinidumpCallback.Invoke(false);
-    return;
-  }
-
-  nsCOMPtr<nsIAsyncShutdownBlocker> shutdownBlocker;
-  if (aAsync && NS_IsMainThread()) {
-    nsCOMPtr<nsIAsyncShutdownClient> barrier = GetShutdownBarrier();
-    if (!barrier) {
-      mCreateMinidumpCallback.Invoke(false);
-      return;
-    }
-
-    shutdownBlocker = new GenerateMinidumpShutdownBlocker();
-
-    nsresult rv = barrier->AddBlocker(shutdownBlocker,
-                                      NS_LITERAL_STRING(__FILE__), __LINE__,
-                                      NS_LITERAL_STRING("Minidump generation"));
-    Unused << NS_WARN_IF(NS_FAILED(rv));
-  }
-
-  std::function<void(bool)> callback =
-    [this, shutdownBlocker](bool aResult) {
-      if (aResult &&
-          CrashReporter::GetIDFromMinidump(this->mTargetDump, this->mDumpID)) {
-        this->mCreateMinidumpCallback.Invoke(true);
-      } else {
-        this->mCreateMinidumpCallback.Invoke(false);
-       }
-
-       if (shutdownBlocker) {
-         nsCOMPtr<nsIAsyncShutdownClient> barrier = GetShutdownBarrier();
-         if (barrier) {
-           barrier->RemoveBlocker(shutdownBlocker);
-         }
-      }
-    };
-
-  CrashReporter::CreateMinidumpsAndPair(childHandle,
-                                        mThreadId,
-                                        aPairName,
-                                        aMinidumpToPair,
-                                        getter_AddRefs(mTargetDump),
-                                        std::move(callback),
-                                        aAsync);
-}
-
 /* static */ void
 CrashReporterHost::NotifyCrashService(GeckoProcessType aProcessType,
                                       int32_t aCrashType,
                                       const nsString& aChildDumpID)
 {
   if (!NS_IsMainThread()) {
     RefPtr<Runnable> runnable = NS_NewRunnableFunction(
       "ipc::CrashReporterHost::NotifyCrashService", [&]() -> void {
--- a/ipc/glue/CrashReporterHost.h
+++ b/ipc/glue/CrashReporterHost.h
@@ -13,89 +13,31 @@
 #include "mozilla/ipc/Shmem.h"
 #include "base/process.h"
 #include "nsExceptionHandler.h"
 #include "nsThreadUtils.h"
 
 namespace mozilla {
 namespace ipc {
 
-class GeckoChildProcessHost;
-
 // This is the newer replacement for CrashReporterParent. It is created in
 // response to a InitCrashReporter message on a top-level actor, and simply
 // holds the metadata shmem alive until the process ends. When the process
 // terminates abnormally, the top-level should call GenerateCrashReport to
 // automatically integrate metadata.
 class CrashReporterHost
 {
   typedef mozilla::ipc::Shmem Shmem;
   typedef CrashReporter::AnnotationTable AnnotationTable;
-  typedef CrashReporter::ThreadId ThreadId;
 
 public:
 
-  template <typename T>
-  class CallbackWrapper {
-  public:
-    void Init(std::function<void(T)>&& aCallback, bool aAsync)
-    {
-      mCallback = std::move(aCallback);
-      mAsync = aAsync;
-      if (IsAsync()) {
-        // Don't call do_GetCurrentThread() if this is called synchronously
-        // because 1. it's unnecessary, and 2. more importantly, it might create
-        // one if called from a native thread, and the thread will be leaked.
-        mTargetThread = do_GetCurrentThread();
-      }
-    }
-
-    bool IsEmpty()
-    {
-      return !mCallback;
-    }
-
-    bool IsAsync()
-    {
-      return mAsync;
-    }
-
-    void Invoke(T aResult)
-    {
-      if (IsAsync()) {
-        decltype(mCallback) callback = std::move(mCallback);
-        mTargetThread->
-          Dispatch(NS_NewRunnableFunction("ipc::CrashReporterHost::CallbackWrapper::Invoke",
-                                          [callback, aResult](){
-                     callback(aResult);
-                   }), NS_DISPATCH_NORMAL);
-      } else {
-        MOZ_ASSERT(!mTargetThread);
-        mCallback(aResult);
-      }
-
-      Clear();
-    }
-
-  private:
-    void Clear()
-    {
-      mCallback = nullptr;
-      mTargetThread = nullptr;
-      mAsync = false;
-    }
-
-    bool mAsync;
-    std::function<void(T)> mCallback;
-    nsCOMPtr<nsIThread> mTargetThread;
-  };
-
   CrashReporterHost(GeckoProcessType aProcessType,
                     const Shmem& aShmem,
-                    ThreadId aThreadId);
+                    CrashReporter::ThreadId aThreadId);
 
   // Helper function for generating a crash report for a process that probably
   // crashed (i.e., had an AbnormalShutdown in ActorDestroy). Returns true if
   // the process has a minidump attached and we were able to generate a report.
   bool GenerateCrashReport(base::ProcessId aPid);
 
   // Given an existing minidump for a crashed child process, take ownership of
   // it from IPDL. After this, FinalizeCrashReport may be called.
@@ -107,25 +49,47 @@ public:
 
   // If a minidump was already captured (e.g. via the hang reporter), this
   // finalizes the existing report by attaching metadata and notifying the
   // crash service.
   bool FinalizeCrashReport();
 
   // Generate a paired minidump. This does not take the crash report, as
   // GenerateCrashReport does. After this, FinalizeCrashReport may be called.
-  // Minidump(s) can be generated synchronously or asynchronously, specified in
-  // argument aAsync. When the operation completes, aCallback is invoked, where
-  // the callback argument denotes whether the operation succeeded.
-  void
-  GenerateMinidumpAndPair(GeckoChildProcessHost* aChildProcess,
-                          nsIFile* aMinidumpToPair,
-                          const nsACString& aPairName,
-                          std::function<void(bool)>&& aCallback,
-                          bool aAsync);
+  //
+  // This calls TakeCrashedChildMinidump and FinalizeCrashReport.
+  template <typename Toplevel>
+  bool GenerateMinidumpAndPair(Toplevel* aToplevelProtocol,
+                               nsIFile* aMinidumpToPair,
+                               const nsACString& aPairName)
+  {
+    ScopedProcessHandle childHandle;
+#ifdef XP_MACOSX
+    childHandle = aToplevelProtocol->Process()->GetChildTask();
+#else
+    if (!base::OpenPrivilegedProcessHandle(aToplevelProtocol->OtherPid(),
+                                           &childHandle.rwget()))
+    {
+      NS_WARNING("Failed to open child process handle.");
+      return false;
+    }
+#endif
+
+    nsCOMPtr<nsIFile> targetDump;
+    if (!CrashReporter::CreateMinidumpsAndPair(childHandle,
+                                               mThreadId,
+                                               aPairName,
+                                               aMinidumpToPair,
+                                               getter_AddRefs(targetDump)))
+    {
+      return false;
+    }
+
+    return CrashReporter::GetIDFromMinidump(targetDump, mDumpID);
+  }
 
   void AddAnnotation(CrashReporter::Annotation aKey, bool aValue);
   void AddAnnotation(CrashReporter::Annotation aKey, int aValue);
   void AddAnnotation(CrashReporter::Annotation aKey, unsigned int aValue);
   void AddAnnotation(CrashReporter::Annotation aKey, const nsCString& aValue);
 
   bool HasMinidump() const {
     return !mDumpID.IsEmpty();
@@ -147,23 +111,21 @@ private:
   // called from the main thread, will post a synchronous message to the
   // main thread.
   static void NotifyCrashService(
     GeckoProcessType aProcessType,
     int32_t aCrashType,
     const nsString& aChildDumpID);
 
 private:
-  CallbackWrapper<bool> mCreateMinidumpCallback;
   GeckoProcessType mProcessType;
   Shmem mShmem;
-  ThreadId mThreadId;
+  CrashReporter::ThreadId mThreadId;
   time_t mStartTime;
   AnnotationTable mExtraAnnotations;
   nsString mDumpID;
   bool mFinalized;
-  nsCOMPtr<nsIFile> mTargetDump;
 };
 
 } // namespace ipc
 } // namespace mozilla
 
 #endif // mozilla_ipc_CrashReporterHost_h
--- a/toolkit/crashreporter/nsDummyExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsDummyExceptionHandler.cpp
@@ -1,14 +1,16 @@
 /* -*- 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 <functional>
+
 #include "nsExceptionHandler.h"
 #include "nsExceptionHandlerUtils.h"
 
 namespace CrashReporter {
 
 void
 AnnotateOOMAllocationSize(size_t size)
 {
@@ -383,25 +385,24 @@ CurrentThreadId()
 }
 
 bool
 TakeMinidump(nsIFile** aResult, bool aMoveToPending)
 {
   return false;
 }
 
-void
+bool
 CreateMinidumpsAndPair(ProcessHandle aTargetPid,
                        ThreadId aTargetBlamedThread,
                        const nsACString& aIncomingPairName,
                        nsIFile* aIncomingDumpToPair,
-                       nsIFile** aMainDumpOut,
-                       std::function<void(bool)>&& aCallback,
-                       bool aAsync)
+                       nsIFile** aTargetDumpOut)
 {
+  return false;
 }
 
 bool
 CreateAdditionalChildMinidump(ProcessHandle childPid,
                               ThreadId childBlamedThread,
                               nsIFile* parentMinidump,
                               const nsACString& name)
 {
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -304,18 +304,16 @@ struct ChildProcessData : public nsUint3
 #endif
 };
 
 typedef nsTHashtable<ChildProcessData> ChildMinidumpMap;
 static ChildMinidumpMap* pidToMinidump;
 static uint32_t crashSequence;
 static bool OOPInitialized();
 
-static nsIThread* sMinidumpWriterThread;
-
 #ifdef MOZ_CRASHREPORTER_INJECTOR
 static nsIThread* sInjectorThread;
 
 class ReportInjectedCrash : public Runnable
 {
 public:
   explicit ReportInjectedCrash(uint32_t pid) : Runnable("ReportInjectedCrash"), mPID(pid) { }
 
@@ -3408,21 +3406,16 @@ OOPDeinit()
 
 #ifdef MOZ_CRASHREPORTER_INJECTOR
   if (sInjectorThread) {
     sInjectorThread->Shutdown();
     NS_RELEASE(sInjectorThread);
   }
 #endif
 
-  if (sMinidumpWriterThread) {
-    sMinidumpWriterThread->Shutdown();
-    NS_RELEASE(sMinidumpWriterThread);
-  }
-
   delete crashServer;
   crashServer = nullptr;
 
   delete dumpMapLock;
   dumpMapLock = nullptr;
 
   delete pidToMinidump;
   pidToMinidump = nullptr;
@@ -3854,177 +3847,95 @@ bool TakeMinidump(nsIFile** aResult, boo
   }
 
   if (aMoveToPending) {
     MoveToPending(*aResult, nullptr, nullptr);
   }
   return true;
 }
 
-static inline void
-NotifyDumpResult(bool aResult,
-                 bool aAsync,
-                 std::function<void(bool)>&& aCallback,
-                 RefPtr<nsIThread>&& aCallbackThread)
+bool
+CreateMinidumpsAndPair(ProcessHandle aTargetPid,
+                       ThreadId aTargetBlamedThread,
+                       const nsACString& aIncomingPairName,
+                       nsIFile* aIncomingDumpToPair,
+                       nsIFile** aMainDumpOut)
 {
-  std::function<void()> runnable = [&](){
-    aCallback(aResult);
-  };
-
-  if (aAsync) {
-    MOZ_ASSERT(!!aCallbackThread);
-    Unused << aCallbackThread->Dispatch(NS_NewRunnableFunction("CrashReporter::InvokeCallback",
-                                                               std::move(runnable)),
-                                        NS_DISPATCH_SYNC);
-  } else {
-    runnable();
+  if (!GetEnabled()) {
+    return false;
   }
-}
-
-static void
-CreatePairedChildMinidumpAsync(ProcessHandle aTargetPid,
-                               ThreadId aTargetBlamedThread,
-                               nsCString aIncomingPairName,
-                               nsCOMPtr<nsIFile> aIncomingDumpToPair,
-                               nsIFile** aMainDumpOut,
-                               xpstring aDumpPath,
-                               std::function<void(bool)>&& aCallback,
-                               RefPtr<nsIThread>&& aCallbackThread,
-                               bool aAsync)
-{
+
   AutoIOInterposerDisable disableIOInterposition;
 
 #ifdef XP_MACOSX
   mach_port_t targetThread = GetChildThread(aTargetPid, aTargetBlamedThread);
 #else
   ThreadId targetThread = aTargetBlamedThread;
 #endif
 
+  xpstring dump_path;
+#ifndef XP_LINUX
+  dump_path = gExceptionHandler->dump_path();
+#else
+  dump_path = gExceptionHandler->minidump_descriptor().directory();
+#endif
+
   // dump the target
   nsCOMPtr<nsIFile> targetMinidump;
   if (!google_breakpad::ExceptionHandler::WriteMinidumpForChild(
          aTargetPid,
          targetThread,
-         aDumpPath,
+         dump_path,
          PairedDumpCallbackExtra,
          static_cast<void*>(&targetMinidump)
 #ifdef XP_WIN32
          , GetMinidumpType()
 #endif
       )) {
-    NotifyDumpResult(false, aAsync, std::move(aCallback), std::move(aCallbackThread));
-    return;
+    return false;
   }
 
   nsCOMPtr<nsIFile> targetExtra;
   GetExtraFileForMinidump(targetMinidump, getter_AddRefs(targetExtra));
-  if (!targetExtra) {
-    targetMinidump->Remove(false);
-
-    NotifyDumpResult(false, aAsync, std::move(aCallback), std::move(aCallbackThread));
-    return;
-  }
-
-  RenameAdditionalHangMinidump(aIncomingDumpToPair,
-                               targetMinidump,
-                               aIncomingPairName);
-
-  if (ShouldReport()) {
-    MoveToPending(targetMinidump, targetExtra, nullptr);
-    MoveToPending(aIncomingDumpToPair, nullptr, nullptr);
-  }
-
-  targetMinidump.forget(aMainDumpOut);
-
-  NotifyDumpResult(true, aAsync, std::move(aCallback), std::move(aCallbackThread));
-}
-
-void
-CreateMinidumpsAndPair(ProcessHandle aTargetPid,
-                       ThreadId aTargetBlamedThread,
-                       const nsACString& aIncomingPairName,
-                       nsIFile* aIncomingDumpToPair,
-                       nsIFile** aMainDumpOut,
-                       std::function<void(bool)>&& aCallback,
-                       bool aAsync)
-{
-  if (!GetEnabled()) {
-    aCallback(false);
-    return;
-  }
-#if defined(DEBUG) && defined(HAS_DLL_BLOCKLIST)
-  DllBlocklist_Shutdown();
-#endif
-
-  AutoIOInterposerDisable disableIOInterposition;
-
-  xpstring dump_path;
-#ifndef XP_LINUX
-  dump_path = gExceptionHandler->dump_path();
-#else
-  dump_path = gExceptionHandler->minidump_descriptor().directory();
-#endif
 
   // If aIncomingDumpToPair isn't valid, create a dump of this process.
-  // This part needs to be synchronous, unfortunately, so that the parent dump
-  // contains the stack symmetrical with the child dump.
-  nsCOMPtr<nsIFile> incomingDumpToPair;
+  nsCOMPtr<nsIFile> incomingDump;
   if (aIncomingDumpToPair == nullptr) {
     if (!google_breakpad::ExceptionHandler::WriteMinidump(
         dump_path,
 #ifdef XP_MACOSX
         true,
 #endif
         PairedDumpCallback,
-        static_cast<void*>(&incomingDumpToPair)
+        static_cast<void*>(&incomingDump)
 #ifdef XP_WIN32
         , GetMinidumpType()
 #endif
         )) {
-      aCallback(false);
-      return;
-    } // else incomingDump is assigned in PairedDumpCallback().
+      targetMinidump->Remove(false);
+      targetExtra->Remove(false);
+      return false;
+    }
   } else {
-    incomingDumpToPair = aIncomingDumpToPair;
-  }
-  MOZ_ASSERT(!!incomingDumpToPair);
-
-  if (aAsync &&
-      !sMinidumpWriterThread &&
-      NS_FAILED(NS_NewNamedThread("Minidump Writer", &sMinidumpWriterThread))) {
-    aCallback(false);
-    return;
+    incomingDump = aIncomingDumpToPair;
   }
 
-  nsCString incomingPairName(aIncomingPairName);
-  std::function<void(bool)> callback = std::move(aCallback);
-  // Don't call do_GetCurrentThread() if this is called synchronously because
-  // 1. it's unnecessary, and 2. more importantly, it might create one if called
-  // from a native thread, and the thread will be leaked.
-  RefPtr<nsIThread> callbackThread = aAsync ? do_GetCurrentThread() : nullptr;
-
-  std::function<void()> doDump = [=]() mutable {
-    CreatePairedChildMinidumpAsync(aTargetPid,
-                                   aTargetBlamedThread,
-                                   incomingPairName,
-                                   incomingDumpToPair,
-                                   aMainDumpOut,
-                                   dump_path,
-                                   std::move(callback),
-                                   std::move(callbackThread),
-                                   aAsync);
-  };
-
-  if (aAsync) {
-    sMinidumpWriterThread->Dispatch(NS_NewRunnableFunction("CrashReporter::CreateMinidumpsAndPair",
-                                                           std::move(doDump)),
-                                    nsIEventTarget::DISPATCH_NORMAL);
-  } else {
-    doDump();
+  RenameAdditionalHangMinidump(incomingDump, targetMinidump, aIncomingPairName);
+
+  if (ShouldReport()) {
+    MoveToPending(targetMinidump, targetExtra, nullptr);
+    MoveToPending(incomingDump, nullptr, nullptr);
   }
+#if defined(DEBUG) && defined(HAS_DLL_BLOCKLIST)
+  DllBlocklist_Shutdown();
+#endif
+
+  targetMinidump.forget(aMainDumpOut);
+
+  return true;
 }
 
 bool
 CreateAdditionalChildMinidump(ProcessHandle childPid,
                               ThreadId childBlamedThread,
                               nsIFile* parentMinidump,
                               const nsACString& name)
 {
--- a/toolkit/crashreporter/nsExceptionHandler.h
+++ b/toolkit/crashreporter/nsExceptionHandler.h
@@ -12,17 +12,16 @@
 #ifndef nsExceptionHandler_h__
 #define nsExceptionHandler_h__
 
 #include "mozilla/Assertions.h"
 #include "mozilla/EnumeratedArray.h"
 
 #include "CrashAnnotations.h"
 
-#include <functional>
 #include <stddef.h>
 #include <stdint.h>
 #include "nsError.h"
 #include "nsString.h"
 #include "prio.h"
 
 #if defined(XP_WIN32)
 #ifdef WIN32_LEAN_AND_MEAN
@@ -229,24 +228,21 @@ ThreadId CurrentThreadId();
  *   passes in.
  * @param aIncomingDumpToPair Existing dump to pair with the new dump. if this
  *   is null, TakeMinidumpAndPair will take a new minidump of the calling
  *   process and thread and use it in aIncomingDumpToPairs place.
  * @param aTargetDumpOut The target minidump file paired up with
  *   aIncomingDumpToPair.
  * @return bool indicating success or failure
  */
-void
-CreateMinidumpsAndPair(ProcessHandle aTargetPid,
-                       ThreadId aTargetBlamedThread,
-                       const nsACString& aIncomingPairName,
-                       nsIFile* aIncomingDumpToPair,
-                       nsIFile** aTargetDumpOut,
-                       std::function<void(bool)>&& aCallback,
-                       bool aAsync);
+bool CreateMinidumpsAndPair(ProcessHandle aTargetPid,
+                            ThreadId aTargetBlamedThread,
+                            const nsACString& aIncomingPairName,
+                            nsIFile* aIncomingDumpToPair,
+                            nsIFile** aTargetDumpOut);
 
 // Create an additional minidump for a child of a process which already has
 // a minidump (|parentMinidump|).
 // The resulting dump will get the id of the parent and use the |name| as
 // an extension.
 bool CreateAdditionalChildMinidump(ProcessHandle childPid,
                                    ThreadId childBlamedThread,
                                    nsIFile* parentMinidump,