Bug 1278325 - Hook exit to catch early 3rd party exits in crash reports. r=ted
authorBenoit Girard <b56girard@gmail.com>
Tue, 07 Jun 2016 15:58:14 -0400
changeset 355195 a42e8a53dc39eee4d27c33b184f8f6d5dff367cb
parent 355194 6949e171dfd4eb17ec9ac17a60fc2a1615b2b6a9
child 355196 483725b39bb2639b164badc7ce5298ba2574f9b2
push id6570
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:26:13 +0000
treeherdermozilla-beta@f455459b2ae5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted
bugs1278325
milestone51.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1278325 - Hook exit to catch early 3rd party exits in crash reports. r=ted MozReview-Commit-ID: 6x6DLcqqkAe
toolkit/xre/nsAppRunner.cpp
toolkit/xre/nsAppRunner.h
toolkit/xre/nsNativeAppSupportUnix.cpp
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -7,22 +7,23 @@
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/ipc/GeckoChildProcessHost.h"
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/ChaosMode.h"
 #include "mozilla/IOInterposer.h"
 #include "mozilla/Likely.h"
+#include "mozilla/MemoryChecking.h"
 #include "mozilla/Poison.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/ScopeExit.h"
 #include "mozilla/Services.h"
 #include "mozilla/ServoBindings.h"
 #include "mozilla/Telemetry.h"
-#include "mozilla/MemoryChecking.h"
 
 #include "nsAppRunner.h"
 #include "mozilla/AppData.h"
 #if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
 #include "nsUpdateDriver.h"
 #endif
 #include "ProfileReset.h"
 
@@ -373,16 +374,35 @@ strimatch(const char* lowerstr, const ch
     ++mixedstr;
   }
 
   if (*mixedstr) return false; // lowerstr is shorter
 
   return true;
 }
 
+static bool gIsExpectedExit = false;
+
+void MozExpectedExit() {
+  gIsExpectedExit = true;
+}
+
+/**
+ * Runs atexit() to catch unexpected exit from 3rd party libraries like the
+ * Intel graphics driver calling exit in an error condition. When they
+ * call exit() to report an error we won't shutdown correctly and wont catch
+ * the issue with our crash reporter.
+ */
+static void UnexpectedExit() {
+  if (!gIsExpectedExit) {
+    gIsExpectedExit = true; // Don't risk re-entrency issues when crashing.
+    MOZ_CRASH("Exit called by third party code.");
+  }
+}
+
 /**
  * Output a string to the user.  This method is really only meant to be used to
  * output last-ditch error messages designed for developers NOT END USERS.
  *
  * @param isError
  *        Pass true to indicate severe errors.
  * @param fmt
  *        printf-style format string followed by arguments.
@@ -3013,16 +3033,21 @@ public:
  */
 int
 XREMain::XRE_mainInit(bool* aExitFlag)
 {
   if (!aExitFlag)
     return 1;
   *aExitFlag = false;
 
+  atexit(UnexpectedExit);
+  auto expectedShutdown = mozilla::MakeScopeExit([&] {
+    MozExpectedExit();
+  });
+
   StartupTimeline::Record(StartupTimeline::MAIN);
 
   if (PR_GetEnv("MOZ_CHAOSMODE")) {
     ChaosFeature feature = ChaosFeature::Any;
     long featureInt = strtol(PR_GetEnv("MOZ_CHAOSMODE"), nullptr, 16);
     if (featureInt) {
       // NOTE: MOZ_CHAOSMODE=0 or a non-hex value maps to Any feature.
       feature = static_cast<ChaosFeature>(featureInt);
--- a/toolkit/xre/nsAppRunner.h
+++ b/toolkit/xre/nsAppRunner.h
@@ -92,16 +92,23 @@ NS_LockProfilePath(nsIFile* aPath, nsIFi
                    nsIProfileUnlocker* *aUnlocker, nsIProfileLock* *aResult);
 
 void
 WriteConsoleLog();
 
 void
 OverrideDefaultLocaleIfNeeded();
 
+/**
+ * Allow exit() calls to complete. This should be done from a proper Gecko
+ * shutdown path. Otherwise we aim to catch improper shutdowns.
+ */
+void
+MozExpectedExit();
+
 #ifdef XP_WIN
 void
 UseParentConsole();
 
 BOOL
 WinLaunchChild(const wchar_t *exePath, int argc,
                char **argv, HANDLE userToken = nullptr,
                HANDLE *hProcess = nullptr);
--- a/toolkit/xre/nsNativeAppSupportUnix.cpp
+++ b/toolkit/xre/nsNativeAppSupportUnix.cpp
@@ -467,16 +467,17 @@ nsNativeAppSupportUnix::Start(bool *aRet
                      GTK_BUTTONS_OK,
                      UNSUPPORTED_GTK_MSG,
                      gtk_major_version,
                      gtk_minor_version,
                      MIN_GTK_MAJOR_VERSION,
                      MIN_GTK_MINOR_VERSION);
     gtk_dialog_run(GTK_DIALOG(versionErrDialog));
     gtk_widget_destroy(versionErrDialog);
+    MozExpectedExit();
     exit(0);
   }
 #endif
 
   *aRetVal = true;
 
 #ifdef MOZ_X11
   gboolean sm_disable = FALSE;