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 97298 a7fce1dd2b5853df71b7e511dbf4a2bf1c4aabb8
parent 97297 db1a0ca3bc67e3714813a828b9fc79a909cef5b3
child 97299 14b79d264b0b07db0511469b81988940aaead90a
push id22968
push useremorley@mozilla.com
push dateFri, 22 Jun 2012 10:29:13 +0000
treeherdermozilla-central@aaa6906f8e92 [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(); \