]> pd.if.org Git - pdclib.old/commitdiff
win32: add a last chance exception handler which invokes the appropriate signal handler
authorOwen Shepherd <owen.shepherd@e43.eu>
Wed, 15 Aug 2012 22:53:54 +0000 (23:53 +0100)
committerOwen Shepherd <owen.shepherd@e43.eu>
Wed, 15 Aug 2012 22:53:54 +0000 (23:53 +0100)
platform/win32/crt0.c

index fcdee084eec3362453825028447a6443d564e463..f7f6a925243cc76ebb59e4b1fe0661abf4f1cd8d 100644 (file)
@@ -2,6 +2,7 @@
 #include <string.h>\r
 #include <stdlib.h>\r
 #include <stdio.h>\r
+#include <signal.h>\r
 \r
 static char ** argvToAnsi( wchar_t ** wargv, int argc )\r
 {\r
@@ -40,6 +41,60 @@ static void freeArgs( void )
     LocalFree( wargv );\r
 }\r
 \r
+extern void (*_PDCLIB_sigfpe)( int );\r
+extern void (*_PDCLIB_sigill)( int );\r
+extern void (*_PDCLIB_sigsegv)( int );\r
+\r
+static LPTOP_LEVEL_EXCEPTION_FILTER oldFilter;\r
+static LONG CALLBACK sehExceptionFilter( EXCEPTION_POINTERS * exInfo )\r
+{\r
+    int sig;\r
+    void (*handler)( int );\r
+\r
+    switch( exInfo->ExceptionRecord->ExceptionCode ) {\r
+        case EXCEPTION_ACCESS_VIOLATION:\r
+        case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:\r
+        case EXCEPTION_DATATYPE_MISALIGNMENT:\r
+        case EXCEPTION_GUARD_PAGE:\r
+        case EXCEPTION_IN_PAGE_ERROR:\r
+        case EXCEPTION_STACK_OVERFLOW:\r
+            sig = SIGSEGV;\r
+            handler = _PDCLIB_sigsegv;\r
+            break;\r
+\r
+        case EXCEPTION_ILLEGAL_INSTRUCTION:\r
+        case EXCEPTION_PRIV_INSTRUCTION:\r
+            sig = SIGILL;\r
+            handler = _PDCLIB_sigill;\r
+            break;\r
+\r
+        case EXCEPTION_INT_DIVIDE_BY_ZERO:\r
+        case EXCEPTION_INT_OVERFLOW:\r
+        case EXCEPTION_FLT_DENORMAL_OPERAND:\r
+        case EXCEPTION_FLT_DIVIDE_BY_ZERO:\r
+        case EXCEPTION_FLT_INEXACT_RESULT:\r
+        case EXCEPTION_FLT_INVALID_OPERATION:\r
+        case EXCEPTION_FLT_OVERFLOW:\r
+        case EXCEPTION_FLT_STACK_CHECK:\r
+        case EXCEPTION_FLT_UNDERFLOW:\r
+            sig = SIGFPE;\r
+            handler = _PDCLIB_sigfpe;\r
+            break;\r
+\r
+        default:\r
+            return oldFilter ? oldFilter( exInfo ) : EXCEPTION_EXECUTE_HANDLER;\r
+    }\r
+\r
+    if(handler == SIG_DFL) {\r
+        return EXCEPTION_EXECUTE_HANDLER;\r
+    } else if(handler == SIG_IGN) {\r
+        return EXCEPTION_CONTINUE_EXECUTION;\r
+    } else {\r
+        handler( sig );\r
+        return EXCEPTION_CONTINUE_EXECUTION;\r
+    }\r
+}\r
+\r
 extern int main( int argc, char ** argv, char ** envp );\r
 _PDCLIB_noreturn void mainCRTStartup( void ) \r
 {\r
@@ -47,11 +102,14 @@ _PDCLIB_noreturn void mainCRTStartup( void )
     stdout->handle = GetStdHandle(STD_OUTPUT_HANDLE);\r
     stderr->handle = GetStdHandle(STD_ERROR_HANDLE);\r
 \r
+    oldFilter = SetUnhandledExceptionFilter( sehExceptionFilter );\r
+\r
     cl    = GetCommandLineW();\r
     wargv = CommandLineToArgvW(cl, &argc);\r
     argv  = argvToAnsi(wargv, argc);\r
     atexit(freeArgs);\r
 \r
     int exitStatus = main(argc, argv, NULL);\r
+\r
     exit(exitStatus);\r
 }\r