0029171: Foundation Classes - C signal handler does not work on MinGW
authorabv <abv@opencascade.com>
Sat, 7 Oct 2017 16:26:38 +0000 (19:26 +0300)
committerbugmaster <bugmaster@opencascade.com>
Wed, 11 Oct 2017 14:13:32 +0000 (17:13 +0300)
Setting signal handler is enabled in OSD::SetSignal() for MinGW (works only for SEH builds of MinGW, not for SJLJ builds).

Due to absence of function _set_se_translator(), handler is set using C signal() function and thus is called asynchronously.
Macro OCC_CONVERT_SIGNALS is enabled for MinGW build to support converting signals to C++ exceptions using long jumps (the same as on Linux).
Code raising exceptions in OSD::SetSignal() is corrected to use method Jump() instead of C++ throw.

adm/cmake/occt_defs_flags.cmake
src/OSD/OSD_signal.cxx

index b938974..41db64a 100644 (file)
@@ -25,7 +25,7 @@ if (NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
   endif()
 endif()
 
-if (WIN32)
+if (MSVC)
   add_definitions (-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE)
 else()
   set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions -fPIC")
index caeab21..30482d4 100644 (file)
 #include <float.h>
 
 static Standard_Boolean fCtrlBrk;
-#if !defined(__CYGWIN32__) && !defined(__MINGW32__)
+
 static Standard_Boolean fMsgBox;
 static Standard_Boolean fFltExceptions;
-static Standard_Boolean fDbgLoaded;
 
 // used to forbid simultaneous execution of setting / executing handlers
 static Standard_Mutex THE_SIGNAL_MUTEX;
@@ -76,13 +75,20 @@ static Standard_Mutex THE_SIGNAL_MUTEX;
 static LONG __fastcall _osd_raise ( DWORD, LPSTR );
 static BOOL WINAPI     _osd_ctrl_break_handler ( DWORD );
 
-#ifndef OCCT_UWP
+#if ! defined(OCCT_UWP) && !defined(__MINGW32__) && !defined(__CYGWIN32__)
+static Standard_Boolean fDbgLoaded;
 static LONG _osd_debug   ( void );
 #endif
 
 //# define _OSD_FPX ( _EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW )
 # define _OSD_FPX ( _EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW )
 
+#ifdef OCC_CONVERT_SIGNALS
+#define THROW_OR_JUMP(Type,Message) Type::NewInstance(Message)->Jump()
+#else
+#define THROW_OR_JUMP(Type,Message) throw Type(Message)
+#endif
+
 //=======================================================================
 //function : CallHandler
 //purpose  :
@@ -148,7 +154,8 @@ static LONG CallHandler (DWORD dwExceptionCode,
       break ;
     case STATUS_NO_MEMORY:
 //      cout << "CallHandler : STATUS_NO_MEMORY:" << endl ;
-      throw OSD_Exception_STATUS_NO_MEMORY (  "MEMORY ALLOCATION ERROR ( no room in the process heap )"  );
+      THROW_OR_JUMP (OSD_Exception_STATUS_NO_MEMORY, "MEMORY ALLOCATION ERROR ( no room in the process heap )");
+      break;
     case EXCEPTION_ACCESS_VIOLATION:
 //      cout << "CallHandler : EXCEPTION_ACCESS_VIOLATION:" << endl ;
       StringCchPrintfW (buffer, _countof(buffer), L"%s%s%s0x%.8p%s%s%s", L"ACCESS VIOLATION",
@@ -227,7 +234,7 @@ static LONG CallHandler (DWORD dwExceptionCode,
     _fpreset();
     _clearfp();
 
-#ifndef OCCT_UWP
+#if ! defined(OCCT_UWP) && !defined(__MINGW32__) && !defined(__CYGWIN32__)
     MessageBeep ( MB_ICONHAND );
     int aChoice = ::MessageBoxW (0, buffer, L"OCCT Exception Handler", MB_ABORTRETRYIGNORE | MB_ICONSTOP);
     if (aChoice == IDRETRY)
@@ -287,7 +294,7 @@ static void SIGWntHandler (int signum, int sub_code)
           break ;
         default:
           cout << "SIGWntHandler(default) -> throw Standard_NumericError(\"Floating Point Error\");" << endl;
-          throw Standard_NumericError("Floating Point Error");
+         THROW_OR_JUMP (Standard_NumericError, "Floating Point Error");
           break ;
       }
       break ;
@@ -309,7 +316,6 @@ static void SIGWntHandler (int signum, int sub_code)
   DebugBreak ();
 #endif
 }
-#endif
 
 //=======================================================================
 //function : TranslateSE
@@ -342,7 +348,6 @@ static void TranslateSE( unsigned int theCode, EXCEPTION_POINTERS* theExcPtr )
 //           option and unless user sets his own exception handler with
 //           ::SetUnhandledExceptionFilter().
 //=======================================================================
-#if !defined(__CYGWIN32__) && !defined(__MINGW32__)
 static LONG WINAPI WntHandler (EXCEPTION_POINTERS *lpXP)
 {
   DWORD               dwExceptionCode = lpXP->ExceptionRecord->ExceptionCode;
@@ -351,7 +356,6 @@ static LONG WINAPI WntHandler (EXCEPTION_POINTERS *lpXP)
                       lpXP->ExceptionRecord->ExceptionInformation[1],
                       lpXP->ExceptionRecord->ExceptionInformation[0]);
 }
-#endif
 
 //=======================================================================
 //function : SetSignal
@@ -359,11 +363,8 @@ static LONG WINAPI WntHandler (EXCEPTION_POINTERS *lpXP)
 //=======================================================================
 void OSD::SetSignal (const Standard_Boolean theFloatingSignal)
 {
-#if !defined(__CYGWIN32__) && !defined(__MINGW32__)
   Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
 #if !defined(OCCT_UWP) || defined(NTDDI_WIN10_TH2)
-  LPTOP_LEVEL_EXCEPTION_FILTER aPreviousFilter;
-
   OSD_Environment env ("CSF_DEBUG_MODE");
   TCollection_AsciiString val = env.Value();
   if (!env.Failed())
@@ -380,7 +381,7 @@ void OSD::SetSignal (const Standard_Boolean theFloatingSignal)
   // when user's code is compiled with /EHs
   // Replaces the existing top-level exception filter for all existing and all future threads
   // in the calling process
-  aPreviousFilter = ::SetUnhandledExceptionFilter (/*(LPTOP_LEVEL_EXCEPTION_FILTER)*/ WntHandler);
+  ::SetUnhandledExceptionFilter (/*(LPTOP_LEVEL_EXCEPTION_FILTER)*/ WntHandler);
 #endif // NTDDI_WIN10_TH2
 
   // Signal handlers will only be used when the method ::raise() will be used
@@ -410,9 +411,6 @@ void OSD::SetSignal (const Standard_Boolean theFloatingSignal)
   else {
     _controlfp (_OSD_FPX, _OSD_FPX); // JR add :
   }
-#else
-  (void)theFloatingSignal; // silence compiler warning on MinGw
-#endif
 }  // end OSD :: SetSignal
 
 //============================================================================
@@ -424,7 +422,7 @@ void OSD::ControlBreak () {
     throw OSD_Exception_CTRL_BREAK ( "*** INTERRUPT ***" );
   }
 }  // end OSD :: ControlBreak
-#if !defined(__MINGW32__) && !defined(__CYGWIN32__)
+
 #ifndef OCCT_UWP
 //============================================================================
 //==== _osd_ctrl_break_handler
@@ -439,6 +437,7 @@ static BOOL WINAPI _osd_ctrl_break_handler ( DWORD dwCode ) {
   return TRUE;
 }  // end _osd_ctrl_break_handler
 #endif
+
 //============================================================================
 //==== _osd_raise
 //============================================================================
@@ -449,54 +448,54 @@ static LONG __fastcall _osd_raise ( DWORD dwCode, LPSTR msg )
   switch (dwCode)
   {
     case EXCEPTION_ACCESS_VIOLATION:
-      throw OSD_Exception_ACCESS_VIOLATION(msg);
+      THROW_OR_JUMP (OSD_Exception_ACCESS_VIOLATION, msg);
       break;
     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
-      throw OSD_Exception_ARRAY_BOUNDS_EXCEEDED(msg);
+      THROW_OR_JUMP (OSD_Exception_ARRAY_BOUNDS_EXCEEDED, msg);
       break;
     case EXCEPTION_DATATYPE_MISALIGNMENT:
-      throw Standard_ProgramError(msg);
+      THROW_OR_JUMP (Standard_ProgramError, msg);
       break;
     case EXCEPTION_ILLEGAL_INSTRUCTION:
-      throw OSD_Exception_ILLEGAL_INSTRUCTION(msg);
+      THROW_OR_JUMP (OSD_Exception_ILLEGAL_INSTRUCTION, msg);
       break;
     case EXCEPTION_IN_PAGE_ERROR:
-      throw OSD_Exception_IN_PAGE_ERROR(msg);
+      THROW_OR_JUMP (OSD_Exception_IN_PAGE_ERROR, msg);
       break;
     case EXCEPTION_INT_DIVIDE_BY_ZERO:
-      throw Standard_DivideByZero(msg);
+      THROW_OR_JUMP (Standard_DivideByZero, msg);
       break;
     case EXCEPTION_INT_OVERFLOW:
-      throw OSD_Exception_INT_OVERFLOW(msg);
+      THROW_OR_JUMP (OSD_Exception_INT_OVERFLOW, msg);
       break;
     case EXCEPTION_INVALID_DISPOSITION:
-      throw OSD_Exception_INVALID_DISPOSITION(msg);
+      THROW_OR_JUMP (OSD_Exception_INVALID_DISPOSITION, msg);
       break;
     case EXCEPTION_NONCONTINUABLE_EXCEPTION:
-      throw OSD_Exception_NONCONTINUABLE_EXCEPTION(msg);
+      THROW_OR_JUMP (OSD_Exception_NONCONTINUABLE_EXCEPTION, msg);
       break;
     case EXCEPTION_PRIV_INSTRUCTION:
-      throw OSD_Exception_PRIV_INSTRUCTION(msg);
+      THROW_OR_JUMP (OSD_Exception_PRIV_INSTRUCTION, msg);
       break;
     case EXCEPTION_STACK_OVERFLOW:
-      throw OSD_Exception_STACK_OVERFLOW(msg);
+      THROW_OR_JUMP (OSD_Exception_STACK_OVERFLOW, msg);
       break;
     case EXCEPTION_FLT_DIVIDE_BY_ZERO:
-      throw Standard_DivideByZero(msg);
+      THROW_OR_JUMP (Standard_DivideByZero, msg);
       break;
     case EXCEPTION_FLT_STACK_CHECK:
     case EXCEPTION_FLT_OVERFLOW:
-      throw Standard_Overflow(msg);
+      THROW_OR_JUMP (Standard_Overflow, msg);
       break;
     case EXCEPTION_FLT_UNDERFLOW:
-      throw Standard_Underflow(msg);
+      THROW_OR_JUMP (Standard_Underflow, msg);
       break;
     case EXCEPTION_FLT_INVALID_OPERATION:
     case EXCEPTION_FLT_DENORMAL_OPERAND:
     case EXCEPTION_FLT_INEXACT_RESULT:
     case STATUS_FLOAT_MULTIPLE_TRAPS:
     case STATUS_FLOAT_MULTIPLE_FAULTS:
-      throw Standard_NumericError(msg);
+      THROW_OR_JUMP (Standard_NumericError, msg);
       break;
     default:
       break;
@@ -504,10 +503,10 @@ static LONG __fastcall _osd_raise ( DWORD dwCode, LPSTR msg )
   return EXCEPTION_EXECUTE_HANDLER;
 }  // end _osd_raise
 
+#if ! defined(OCCT_UWP) && !defined(__MINGW32__) && !defined(__CYGWIN32__)
 //============================================================================
 //==== _osd_debug
 //============================================================================
-#ifndef OCCT_UWP
 LONG _osd_debug ( void ) {
 
   LONG action ;
@@ -590,10 +589,9 @@ LONG _osd_debug ( void ) {
   return action ;
 
 }  // end _osd_debug
+#endif /* ! OCCT_UWP && ! __CYGWIN__ && ! __MINGW32__ */
 
-#endif
-#endif
-#else
+#else /* ! _WIN32 */
 
 //---------- All Systems except Windows NT : ----------------------------------
 
@@ -1031,7 +1029,7 @@ void OSD :: ControlBreak ()
 {
   if ( fCtrlBrk ) {
     fCtrlBrk = Standard_False;
-    throw OSD_Exception_CTRL_BREAK("*** INTERRUPT ***");
+    throw OSD_Exception_CTRL_BREAK ("*** INTERRUPT ***");
   }
 }