Bug 1333223 - Add an unhandled exception handler. r=ted, a=lizzard
authorMike Conley <mconley@mozilla.com>
Sun, 29 Jan 2017 02:53:50 -0500
changeset 376269 4f962e1b4f853341fea61b971c5611fb20d91091
parent 376268 ae419dfaebbc4c174aa64d323475b4ee1ab73717
child 376270 13018e92b17958dcde86fb4780a543c33129d056
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted, lizzard
bugs1333223
milestone53.0a2
Bug 1333223 - Add an unhandled exception handler. r=ted, a=lizzard The exception handler calls MOZ_CRASH, which should allow our crash reporting infrastructure to kick in. MozReview-Commit-ID: FzTlXOIMzal
toolkit/crashreporter/nsExceptionHandler.cpp
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -251,16 +251,18 @@ static uint32_t eventloopNestingLevel = 
 
 // Avoid a race during application termination.
 static Mutex* dumpSafetyLock;
 static bool isSafeToDump = false;
 
 // OOP crash reporting
 static CrashGenerationServer* crashServer; // chrome process has this
 
+static std::terminate_handler oldTerminateHandler = nullptr;
+
 #if (defined(XP_MACOSX) || defined(XP_WIN))
 // This field is valid in both chrome and content processes.
 static xpstring* childProcessTmpDir = nullptr;
 #endif
 
 #  if defined(XP_WIN) || defined(XP_MACOSX)
 // If crash reporting is disabled, we hand out this "null" pipe to the
 // child process and don't attempt to connect to a parent server.
@@ -1547,16 +1549,21 @@ ChildFilter(void* context)
 {
   bool result = Filter(context);
   if (result) {
     PrepareChildExceptionTimeAnnotations();
   }
   return result;
 }
 
+void TerminateHandler()
+{
+  MOZ_CRASH("Unhandled exception");
+}
+
 #if !defined(MOZ_WIDGET_ANDROID)
 
 // Locate the specified executable and store its path as a native string in
 // the |aPathPtr| so we can later invoke it from within the exception handler.
 static nsresult
 LocateExecutable(nsIFile* aXREDirectory, const nsACString& aName,
                  nsAString& aPath)
 {
@@ -1815,16 +1822,18 @@ nsresult SetExceptionHandler(nsIFile* aX
                                       library_mappings[i].start_address,
                                       library_mappings[i].length,
                                       library_mappings[i].file_offset);
   }
 #endif
 
   mozalloc_set_oom_abort_handler(AnnotateOOMAllocationSize);
 
+  oldTerminateHandler = std::set_terminate(&TerminateHandler);
+
   return NS_OK;
 }
 
 bool GetEnabled()
 {
   return gExceptionHandler != nullptr;
 }
 
@@ -2152,16 +2161,18 @@ nsresult UnsetExceptionHandler()
 
   gExceptionHandler = nullptr;
 
   OOPDeinit();
 
   delete dumpSafetyLock;
   dumpSafetyLock = nullptr;
 
+  std::set_terminate(oldTerminateHandler);
+
   return NS_OK;
 }
 
 static void ReplaceChar(nsCString& str, const nsACString& character,
                         const nsACString& replacement)
 {
   nsCString::const_iterator iter, end;
 
@@ -3770,16 +3781,18 @@ SetRemoteExceptionHandler(const nsACStri
                      google_breakpad::ExceptionHandler::HANDLER_ALL,
                      GetMinidumpType(),
                      NS_ConvertASCIItoUTF16(crashPipe).get(),
                      nullptr);
   gExceptionHandler->set_handle_debug_exceptions(true);
 
   mozalloc_set_oom_abort_handler(AnnotateOOMAllocationSize);
 
+  oldTerminateHandler = std::set_terminate(&TerminateHandler);
+
   // we either do remote or nothing, no fallback to regular crash reporting
   return gExceptionHandler->IsOutOfProcess();
 }
 
 //--------------------------------------------------
 #elif defined(XP_LINUX)
 
 // Parent-side API for children
@@ -3821,16 +3834,18 @@ SetRemoteExceptionHandler()
     for (uint32_t i = 0; i < gDelayedAnnotations->Length(); i++) {
       gDelayedAnnotations->ElementAt(i)->Run();
     }
     delete gDelayedAnnotations;
   }
 
   mozalloc_set_oom_abort_handler(AnnotateOOMAllocationSize);
 
+  oldTerminateHandler = std::set_terminate(&TerminateHandler);
+
   // we either do remote or nothing, no fallback to regular crash reporting
   return gExceptionHandler->IsOutOfProcess();
 }
 
 //--------------------------------------------------
 #elif defined(XP_MACOSX)
 // Child-side API
 bool
@@ -3847,16 +3862,18 @@ SetRemoteExceptionHandler(const nsACStri
                      ChildFilter,
                      nullptr,    // no minidump callback
                      nullptr,    // no callback context
                      true,       // install signal handlers
                      crashPipe.BeginReading());
 
   mozalloc_set_oom_abort_handler(AnnotateOOMAllocationSize);
 
+  oldTerminateHandler = std::set_terminate(&TerminateHandler);
+
   // we either do remote or nothing, no fallback to regular crash reporting
   return gExceptionHandler->IsOutOfProcess();
 }
 #endif  // XP_WIN
 
 
 bool
 TakeMinidumpForChild(uint32_t childPid, nsIFile** dump, uint32_t* aSequence)
@@ -4162,16 +4179,17 @@ CreateAdditionalChildMinidump(ProcessHan
   RenameAdditionalHangMinidump(childMinidump, parentMinidump, name);
 
   return true;
 }
 
 bool
 UnsetRemoteExceptionHandler()
 {
+  std::set_terminate(oldTerminateHandler);
   delete gExceptionHandler;
   gExceptionHandler = nullptr;
   return true;
 }
 
 #if defined(MOZ_WIDGET_ANDROID)
 void SetNotificationPipeForChild(int childCrashFd)
 {