Bug 589495 - Win32 native exceptions (which could be crashes) on WoW64 are not fatal; r=bsmedberg a=blocking-betaN
authorEhsan Akhgari <ehsan@mozilla.com>
Fri, 11 Feb 2011 20:56:11 -0500
changeset 62476 3510c76c789f143101347d7d5e004a2dda650477
parent 62475 652d012f9dc8f318cd4baccedc982990d3c3c462
child 62477 720d17e280230b308d75901f40bbff1e939cbcd5
push id18737
push usereakhgari@mozilla.com
push dateSat, 12 Feb 2011 19:37:20 +0000
treeherdermozilla-central@e9899b77c6ea [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg, blocking-betaN
bugs589495
milestone2.0b12pre
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 589495 - Win32 native exceptions (which could be crashes) on WoW64 are not fatal; r=bsmedberg a=blocking-betaN
dom/plugins/PluginInstanceChild.cpp
dom/plugins/PluginInstanceChild.h
modules/plugin/base/src/Makefile.in
modules/plugin/base/src/nsPluginNativeWindowWin.cpp
widget/src/windows/Makefile.in
widget/src/windows/nsWindow.cpp
xpcom/base/Makefile.in
xpcom/base/nsCrashOnException.cpp
xpcom/base/nsCrashOnException.h
--- a/dom/plugins/PluginInstanceChild.cpp
+++ b/dom/plugins/PluginInstanceChild.cpp
@@ -73,16 +73,20 @@ using namespace mozilla::plugins;
 #include <QX11Info>
 #elif defined(OS_WIN)
 #ifndef WM_MOUSEHWHEEL
 #define WM_MOUSEHWHEEL     0x020E
 #endif
 
 #include "nsWindowsDllInterceptor.h"
 
+#ifdef _MSC_VER
+#include "nsCrashOnException.h"
+#endif
+
 typedef BOOL (WINAPI *User32TrackPopupMenu)(HMENU hMenu,
                                             UINT uFlags,
                                             int x,
                                             int y,
                                             int nReserved,
                                             HWND hWnd,
                                             CONST RECT *prcRect);
 static WindowsDllInterceptor sUser32Intercept;
@@ -1136,16 +1140,30 @@ PluginInstanceChild::DummyWindowProc(HWN
 
 // static
 LRESULT CALLBACK
 PluginInstanceChild::PluginWindowProc(HWND hWnd,
                                       UINT message,
                                       WPARAM wParam,
                                       LPARAM lParam)
 {
+#ifdef _MSC_VER
+  return mozilla::CallWindowProcCrashProtected(PluginWindowProcInternal, hWnd, message, wParam, lParam);
+#else
+  return PluginWindowProcInternal(hWnd, message, wParam, lParam);
+#endif
+}
+
+// static
+LRESULT CALLBACK
+PluginInstanceChild::PluginWindowProcInternal(HWND hWnd,
+                                              UINT message,
+                                              WPARAM wParam,
+                                              LPARAM lParam)
+{
     NS_ASSERTION(!mozilla::ipc::SyncChannel::IsPumpingMessages(),
                  "Failed to prevent a nonqueued message from running!");
     PluginInstanceChild* self = reinterpret_cast<PluginInstanceChild*>(
         GetProp(hWnd, kPluginInstanceChildProperty));
     if (!self) {
         NS_NOTREACHED("Badness!");
         return 0;
     }
--- a/dom/plugins/PluginInstanceChild.h
+++ b/dom/plugins/PluginInstanceChild.h
@@ -73,16 +73,20 @@ class PluginInstanceChild : public PPlug
     friend class PluginStreamChild;
     friend class StreamNotifyChild; 
 
 #ifdef OS_WIN
     friend LRESULT CALLBACK PluginWindowProc(HWND hWnd,
                                              UINT message,
                                              WPARAM wParam,
                                              LPARAM lParam);
+    static LRESULT CALLBACK PluginWindowProcInternal(HWND hWnd,
+                                                     UINT message,
+                                                     WPARAM wParam,
+                                                     LPARAM lParam);
 #endif
 
 protected:
     virtual bool AnswerNPP_SetWindow(const NPRemoteWindow& window);
 
     virtual bool
     AnswerNPP_GetValue_NPPVpluginNeedsXEmbed(bool* needs, NPError* rv);
     virtual bool
--- a/modules/plugin/base/src/Makefile.in
+++ b/modules/plugin/base/src/Makefile.in
@@ -97,16 +97,20 @@ else
 	CPPSRCS += nsPluginNativeWindow.cpp
 endif
 endif
 endif
 endif
 endif
 endif
 
+LOCAL_INCLUDES = \
+  -I$(topsrcdir)/xpcom/base/ \
+  $(NULL)
+
 ifneq (,$(filter WINNT Darwin,$(OS_ARCH)))
 EXTRA_DSO_LIBS	+= gkgfx
 endif
 
 EXTRA_DSO_LDOPTS = \
 		$(LIBS_DIR) \
 		$(EXTRA_DSO_LIBS) \
 		$(MOZ_NECKO_UTIL_LIBS) \
--- a/modules/plugin/base/src/nsPluginNativeWindowWin.cpp
+++ b/modules/plugin/base/src/nsPluginNativeWindowWin.cpp
@@ -54,16 +54,20 @@
 #include "nsGUIEvent.h"
 #include "nsWindowsDllInterceptor.h"
 #include "nsPluginSafety.h"
 #include "nsPluginNativeWindow.h"
 #include "nsThreadUtils.h"
 #include "nsAutoPtr.h"
 #include "nsTWeakRef.h"
 
+#ifdef _MSC_VER
+#include "nsCrashOnException.h"
+#endif
+
 #define NP_POPUP_API_VERSION 16
 
 #define nsMajorVersion(v)       (((PRInt32)(v) >> 16) & 0xffff)
 #define nsMinorVersion(v)       ((PRInt32)(v) & 0xffff)
 #define versionOK(suppliedV, requiredV)                   \
   (nsMajorVersion(suppliedV) == nsMajorVersion(requiredV) \
    && nsMinorVersion(suppliedV) >= nsMinorVersion(requiredV))
 
@@ -219,17 +223,17 @@ NS_IMETHODIMP nsDelayedPopupsEnabledEven
 {
   mInst->PushPopupsEnabledState(PR_FALSE);
   return NS_OK;	
 }
 
 /**
  *   New plugin window procedure
  */
-static LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+static LRESULT CALLBACK PluginWndProcInternal(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
   nsPluginNativeWindowWin * win = (nsPluginNativeWindowWin *)::GetProp(hWnd, NS_PLUGIN_WINDOW_PROPERTY_ASSOCIATION);
   if (!win)
     return TRUE;
 
   // The DispatchEvent(NS_PLUGIN_ACTIVATE) below can trigger a reentrant focus
   // event which might destroy us.  Hold a strong ref on the plugin instance
   // to prevent that, bug 374229.
@@ -377,16 +381,25 @@ static LRESULT CALLBACK PluginWndProc(HW
     nsCOMPtr<nsIRunnable> event = new nsDelayedPopupsEnabledEvent(inst);
     if (event)
       NS_DispatchToCurrentThread(event);
   }
 
   return res;
 }
 
+static LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+#ifdef _MSC_VER
+  return mozilla::CallWindowProcCrashProtected(PluginWndProcInternal, hWnd, msg, wParam, lParam);
+#else
+  return PluginWndProcInternal(hWnd, msg, wParam, lParam);
+#endif
+}
+
 /*
  * Flash will reset the subclass of our widget at various times.
  * (Notably when entering and exiting full screen mode.) This
  * occurs independent of the main plugin window event procedure.
  * We trap these subclass calls to prevent our subclass hook from
  * getting dropped.
  * Note, ascii versions can be nixed once flash versions < 10.1
  * are considered obsolete.
--- a/widget/src/windows/Makefile.in
+++ b/widget/src/windows/Makefile.in
@@ -127,16 +127,17 @@ endif # BUILD_STATIC_LIBS
 
 EXPORTS		= nsdefs.h WindowHook.h
 
 LOCAL_INCLUDES	= \
 		-I. \
 		-I$(srcdir)/../xpwidgets \
 		-I$(srcdir) \
 		-I$(topsrcdir)/toolkit/xre \
+		-I$(topsrcdir)/xpcom/base \
 		$(NULL)
 
 FORCE_STATIC_LIB = 1
 
 ifdef WINCE
 EXTRA_DSO_LDOPTS += ddraw.lib
 endif
 
--- a/widget/src/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -224,18 +224,18 @@
 #include "mozilla/FunctionTimer.h"
 
 #ifdef WINCE_WINDOWS_MOBILE
 #include "nsGfxCIID.h"
 #endif
 
 #include "mozilla/FunctionTimer.h"
 
-#ifdef MOZ_CRASHREPORTER
-#include "nsICrashReporter.h"
+#ifdef _MSC_VER
+#include "nsCrashOnException.h"
 #endif
 
 #include "nsIXULRuntime.h"
 
 using namespace mozilla::widget;
 using namespace mozilla::layers;
 
 /**************************************************************
@@ -4470,29 +4470,16 @@ nsWindow::IPCWindowProcHandler(UINT& msg
  *
  * SECTION: Wind proc.
  *
  * The main Windows event procedures and associated
  * message processing methods.
  *
  **************************************************************/
 
-#ifdef _MSC_VER
-static int ReportException(EXCEPTION_POINTERS *aExceptionInfo)
-{
-#ifdef MOZ_CRASHREPORTER
-  nsCOMPtr<nsICrashReporter> cr =
-    do_GetService("@mozilla.org/toolkit/crash-reporter;1");
-  if (cr)
-    cr->WriteMinidumpForException(aExceptionInfo);
-#endif
-  return EXCEPTION_EXECUTE_HANDLER;
-}
-#endif
-
 static PRBool
 DisplaySystemMenu(HWND hWnd, nsSizeMode sizeMode, PRBool isRtl, PRInt32 x, PRInt32 y)
 {
   GetSystemMenu(hWnd, TRUE); // reset the system menu
   HMENU hMenu = GetSystemMenu(hWnd, FALSE);
   if (hMenu) {
     // update the options
     switch(sizeMode) {
@@ -4526,22 +4513,17 @@ DisplaySystemMenu(HWND hWnd, nsSizeMode 
 }
 
 // The WndProc procedure for all nsWindows in this toolkit. This merely catches
 // exceptions and passes the real work to WindowProcInternal. See bug 587406
 // and http://msdn.microsoft.com/en-us/library/ms633573%28VS.85%29.aspx
 LRESULT CALLBACK nsWindow::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
 #ifdef _MSC_VER
-  __try {
-    return WindowProcInternal(hWnd, msg, wParam, lParam);
-  }
-  __except(ReportException(GetExceptionInformation())) {
-    ::TerminateProcess(::GetCurrentProcess(), 253);
-  }
+  return mozilla::CallWindowProcCrashProtected(WindowProcInternal, hWnd, msg, wParam, lParam);
 #else
   return WindowProcInternal(hWnd, msg, wParam, lParam);
 #endif
 }
 
 LRESULT CALLBACK nsWindow::WindowProcInternal(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
   NS_TIME_FUNCTION_MIN_FMT(5.0, "%s (line %d) (hWnd: %p, msg: %p, wParam: %p, lParam: %p",
--- a/xpcom/base/Makefile.in
+++ b/xpcom/base/Makefile.in
@@ -93,16 +93,17 @@ EXPORTS		= \
 EXPORTS_NAMESPACES = mozilla
 
 EXPORTS_mozilla = \
 	FunctionTimer.h \
 	$(NULL)
 
 ifeq (windows,$(MOZ_WIDGET_TOOLKIT))
 CPPSRCS += nsSetDllDirectory.cpp
+CPPSRCS += nsCrashOnException.cpp
 endif
 
 ifeq ($(OS_ARCH),WINNT)
 ifdef MOZ_DEBUG
 CSRCS		+= pure_api.c
 EXPORTS		+= pure.h
 endif
 endif
new file mode 100644
--- /dev/null
+++ b/xpcom/base/nsCrashOnException.cpp
@@ -0,0 +1,78 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ehsan Akhgari <ehsan@mozilla.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _MSC_VER
+#error This file only makes sense on Windows.
+#endif
+
+#include "nsCrashOnException.h"
+#include "nsCOMPtr.h"
+#include "nsServiceManagerUtils.h"
+
+#ifdef MOZ_CRASHREPORTER
+#include "nsICrashReporter.h"
+#endif
+
+namespace mozilla {
+
+static int ReportException(EXCEPTION_POINTERS *aExceptionInfo)
+{
+#ifdef MOZ_CRASHREPORTER
+  nsCOMPtr<nsICrashReporter> cr =
+    do_GetService("@mozilla.org/toolkit/crash-reporter;1");
+  if (cr)
+    cr->WriteMinidumpForException(aExceptionInfo);
+#endif
+  return EXCEPTION_EXECUTE_HANDLER;
+}
+
+XPCOM_API(LRESULT)
+CallWindowProcCrashProtected(WNDPROC wndProc, HWND hWnd, UINT msg,
+                            WPARAM wParam, LPARAM lParam)
+{
+  __try {
+    return wndProc(hWnd, msg, wParam, lParam);
+  }
+  __except(ReportException(GetExceptionInformation())) {
+    ::TerminateProcess(::GetCurrentProcess(), 253);
+  }
+  return 0; // not reached
+}
+
+}
+
new file mode 100644
--- /dev/null
+++ b/xpcom/base/nsCrashOnException.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ehsan Akhgari <ehsan@mozilla.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsCrashOnException_h
+#define nsCrashOnException_h
+
+#ifndef _MSC_VER
+#error This file only makes sense on Windows with Visual C++.
+#endif
+
+#include <nscore.h>
+#include <windows.h>
+
+namespace mozilla {
+
+// Call a given window procedure, and catch any Win32 exceptions raised from it,
+// and report them as crashes.
+XPCOM_API(LRESULT) CallWindowProcCrashProtected(WNDPROC wndProc, HWND hWnd, UINT msg,
+                                               WPARAM wParam, LPARAM lParam);
+
+}
+
+#endif