[Piglit] [PATCH] tests: Narrow down the scope of Windows unhandled exception filter.

Jose Fonseca jfonseca at vmware.com
Fri Apr 17 15:16:00 PDT 2015


The previous unhandled exception filter had two problems:

- Vectored exceptions filter are too big of a hammer for this, as they
  intercept any exception on any thread, regardless they have a regular
  handler that will catch them or not.  Whereas we're only interested
  in the uncaught exceptions inside WndProc callback.

- Waffle does not need this.  Unlike GLUT, Waffle lets the piglit
  framework run the main loop, and the display callback function is not
  called inside WndProc callback.

In short, the exception filter could very easily be called for harmless
exceptions (such as internal exceptions used by the OpenGL driver.)

That said, we can't use SetUnhandledExceptionFilter and must actually
use the MSVC's __try/__except keywords, but these are not supported by
MinGW, which only provides much less friendlier __try1/__except1 macros.

Tested Mingw32, Mingw64, and MSVC32 builds of build with FreeGLUT.
---
 .../piglit-framework-gl/piglit_glut_framework.c    | 79 ++++++++++++++++++++++
 tests/util/piglit-util.c                           | 64 ------------------
 2 files changed, 79 insertions(+), 64 deletions(-)

diff --git a/tests/util/piglit-framework-gl/piglit_glut_framework.c b/tests/util/piglit-framework-gl/piglit_glut_framework.c
index 71c640a..dd5eaae 100644
--- a/tests/util/piglit-framework-gl/piglit_glut_framework.c
+++ b/tests/util/piglit-framework-gl/piglit_glut_framework.c
@@ -56,14 +56,93 @@ destroy(struct piglit_gl_framework *gl_fw)
 	glut_fw.window = 0;
 }
 
+
+#ifdef _WIN32
+
+/* Catch any exceptions and abort immediately.
+ *
+ * At least with certain implementations of GLUT (namely
+ * freeglut-2.8.1), the glutDisplayFunc()'s callback called inside a
+ * WindowProc callback function.
+ *
+ * And on certain cases (depending on the Windows version and 32 vs 64
+ * bits processes) uncaught exceptions inside WindowProc callbacks are
+ * silently ignored!  (See Remarks section of
+ * http://msdn.microsoft.com/en-us/library/windows/desktop/ms633573.aspx
+ * page.)   The end result is that automatic tests end up blocking
+ * waiting for user input when an uncaught exceptionhappens, as control
+ * flow is interrupted before it reaches piglit_report_result(), and
+ * the process never aborts.
+ *
+ * By installing our own exception handler we can ensure that uncaught
+ * exceptions will never be silently ignored.
+ *
+ * NOTE: SetUnhandledExceptionFilter does not work here, as some Windows
+ * versions never call the unhandled exception filter.  We must use MSVC
+ * __try/__except statements, or in MinGW, the __try1/__except1 macros.
+ */
+static LONG WINAPI
+exception_filter(PEXCEPTION_POINTERS pExceptionInfo)
+{
+	PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
+
+	fflush(stdout);
+	fprintf(stderr, "error: caught unhandled exception 0x%08lx\n", pExceptionRecord->ExceptionCode);
+	fflush(stderr);
+
+	_exit(pExceptionRecord->ExceptionCode);
+}
+
+#  ifdef __MINGW32__
+
+// http://www.programmingunlimited.net/siteexec/content.cgi?page=mingw-seh
+// http://www.microsoft.com/msj/0197/exception/exception.aspx
+EXCEPTION_DISPOSITION
+exception_handler(struct _EXCEPTION_RECORD *ExceptionRecord, void *EstablisherFrame, struct _CONTEXT *ContextRecord, void *DispatcherContext)
+{
+	EXCEPTION_POINTERS ExceptionInfo = {ExceptionRecord, ContextRecord};
+	switch (exception_filter(&ExceptionInfo)) {
+	case EXCEPTION_EXECUTE_HANDLER:
+		return ExceptionExecuteHandler;
+	case EXCEPTION_CONTINUE_SEARCH:
+		return ExceptionContinueSearch;
+	case EXCEPTION_CONTINUE_EXECUTION:
+		return ExceptionContinueExecution;
+	default:
+		return ExceptionContinueSearch;
+	}
+}
+
+#  define TRY __try1(exception_handler);
+#  define CATCH_ALL __except1;
+
+#  else
+
+#    define TRY __try {
+#    define CATCH_ALL } __except(exception_filter(GetExceptionInformation())) {}
+
+#  endif
+
+#else
+
+#  define TRY
+#  define CATCH_ALL
+
+#endif
+
+
 static void
 display(void)
 {
 	const struct piglit_gl_test_config *test_config = glut_fw.gl_fw.test_config;
 
+	TRY
+
 	if (test_config->display)
 		glut_fw.result = test_config->display();
 
+	CATCH_ALL
+
 	if (piglit_automatic) {
 		glutDestroyWindow(glut_fw.window);
 #ifdef FREEGLUT
diff --git a/tests/util/piglit-util.c b/tests/util/piglit-util.c
index 743373a..9bd0cd2 100644
--- a/tests/util/piglit-util.c
+++ b/tests/util/piglit-util.c
@@ -289,50 +289,6 @@ piglit_report_subtest_result(enum piglit_result result, const char *format, ...)
 	va_end(ap);
 }
 
-#ifdef _WIN32
-
-#ifndef DBG_PRINTEXCEPTION_C
-#define DBG_PRINTEXCEPTION_C 0x40010006
-#endif
-
-static LONG WINAPI
-exception_handler(PEXCEPTION_POINTERS pExceptionInfo)
-{
-	PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
-
-	/* Ignore OutputDebugStringA exceptions. */
-	if (pExceptionRecord->ExceptionCode == DBG_PRINTEXCEPTION_C) {
-		return EXCEPTION_CONTINUE_SEARCH;
-	}
-
-	/* Ignore C++ exceptions
-	 * http://support.microsoft.com/kb/185294
-	 * http://blogs.msdn.com/b/oldnewthing/archive/2010/07/30/10044061.aspx
-	 */
-	if (pExceptionRecord->ExceptionCode == 0xe06d7363) {
-		return EXCEPTION_CONTINUE_SEARCH;
-	}
-
-	/* Ignore thread naming exception.
-	 * http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
-	 */
-	if (pExceptionRecord->ExceptionCode == 0x406d1388) {
-		return EXCEPTION_CONTINUE_SEARCH;
-	}
-
-	fflush(stdout);
-	fprintf(stderr, "error: uncaught exception 0x%08lx\n",
-		pExceptionRecord->ExceptionCode);
-	fflush(stderr);
-
-	TerminateProcess(GetCurrentProcess(),
-			 pExceptionRecord->ExceptionCode);
-
-	return EXCEPTION_CONTINUE_SEARCH;
-}
-
-#endif /* _WIN32 */
-
 
 void
 piglit_disable_error_message_boxes(void)
@@ -367,26 +323,6 @@ piglit_disable_error_message_boxes(void)
 		_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
 #endif
 	}
-
-	/* Catch any exceptions and abort immediately.
-	 *
-	 * At least with certain implementations of GLUT (namely
-	 * freeglut-2.8.1), the glutDisplayFunc()'s callback called inside a
-	 * WindowProc callback function.
-	 *
-	 * And on certain cases (depending on the Windows version and 32 vs 64
-	 * bits processes) uncaught exceptions inside WindowProc callbacks are
-	 * silently ignored!  (See Remarks section of
-	 * http://msdn.microsoft.com/en-us/library/windows/desktop/ms633573.aspx
-	 * page.)   The end result is that automatic tests end up blocking
-	 * waiting for user input when an uncaught exceptionhappens, as control
-	 * flow is interrupted before it reaches piglit_report_result(), and
-	 * the process never aborts.
-	 *
-	 * By installing our own exception handler we can ensure that uncaught
-	 * exceptions will never be silently ignored.
-	 */
-	AddVectoredExceptionHandler(0, exception_handler);
 #endif /* _WIN32 */
 }
 
-- 
2.1.0



More information about the Piglit mailing list