Bug 426163 - Make MOZ_CRASH() use TerminateProcess on Windows rather than exit so that destructors and atexit handlers aren't called. r=ted
authorJeff Walden <jwalden@mit.edu>
Mon, 11 Jun 2012 16:16:46 -0700
changeset 102528 79f9a61a1e435a936b2d7196e081906601b5ff1d
parent 102527 e6875768cb49ca356096bce2ae6aed299d450dd5
child 102529 b3067d05a76a2bc8c3f5f4fb1bb30464a2c6a0fa
push id191
push userlsblakk@mozilla.com
push dateFri, 05 Oct 2012 17:12:53 +0000
treeherdermozilla-release@ddb22ac6c03b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted
bugs426163
milestone16.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 426163 - Make MOZ_CRASH() use TerminateProcess on Windows rather than exit so that destructors and atexit handlers aren't called. r=ted
mfbt/Assertions.h
--- a/mfbt/Assertions.h
+++ b/mfbt/Assertions.h
@@ -8,17 +8,33 @@
 #ifndef mozilla_Assertions_h_
 #define mozilla_Assertions_h_
 
 #include "mozilla/Attributes.h"
 #include "mozilla/Types.h"
 
 #include <stdio.h>
 #include <stdlib.h>
-#ifndef WIN32
+#ifdef WIN32
+   /*
+    * TerminateProcess and GetCurrentProcess are defined in <winbase.h>, which
+    * further depends on <windef.h>.  We hardcode these few definitions manually
+    * because those headers clutter the global namespace with a significant
+    * number of undesired macros and symbols.
+    */
+#  ifdef __cplusplus
+   extern "C" {
+#  endif
+   __declspec(dllimport) int __stdcall
+   TerminateProcess(void* hProcess, unsigned int uExitCode);
+   __declspec(dllimport) void* __stdcall GetCurrentProcess(void);
+#  ifdef __cplusplus
+   }
+#  endif
+#else
 #  include <signal.h>
 #endif
 #ifdef ANDROID
 #  include <android/log.h>
 #endif
 
 /*
  * MOZ_STATIC_ASSERT may be used to assert a condition *at compile time*.  This
@@ -115,32 +131,40 @@ extern "C" {
  * in release builds as well as debug builds.  But if the failure is one that
  * should be debugged and fixed, MOZ_ASSERT is generally preferable.
  */
 #if defined(_MSC_VER)
    /*
     * On MSVC use the __debugbreak compiler intrinsic, which produces an inline
     * (not nested in a system function) breakpoint.  This distinctively invokes
     * Breakpad without requiring system library symbols on all stack-processing
-    * machines, as a nested breakpoint would require.  (Technically all Windows
-    * compilers would require this, but practically only MSVC matters.)
+    * machines, as a nested breakpoint would require.  We use TerminateProcess
+    * with the exit code aborting would generate because we don't want to invoke
+    * atexit handlers, destructors, library unload handlers, and so on when our
+    * process might be in a compromised state.  We don't use abort() because
+    * it'd cause Windows to annoyingly pop up the process error dialog multiple
+    * times.  See bug 345118 and bug 426163.
+    *
+    * (Technically these are Windows requirements, not MSVC requirements.  But
+    * practically you need MSVC for debugging, and we only ship builds created
+    * by MSVC, so doing it this way reduces complexity.)
     */
 #  ifdef __cplusplus
 #    define MOZ_CRASH() \
        do { \
          __debugbreak(); \
          *((volatile int*) NULL) = 123; \
-         ::exit(3); \
+         ::TerminateProcess(::GetCurrentProcess(), 3); \
        } while (0)
 #  else
 #    define MOZ_CRASH() \
        do { \
          __debugbreak(); \
          *((volatile int*) NULL) = 123; \
-         exit(3); \
+         TerminateProcess(GetCurrentProcess(), 3); \
        } while (0)
 #  endif
 #else
 #  ifdef __cplusplus
 #    define MOZ_CRASH() \
        do { \
          *((volatile int*) NULL) = 123; \
          ::abort(); \