From: abv Date: Sat, 7 Oct 2017 16:26:38 +0000 (+0300) Subject: 0029171: Foundation Classes - C signal handler does not work on MinGW X-Git-Tag: V7_3_0_beta~218 X-Git-Url: http://git.dev.opencascade.org/gitweb/?p=occt.git;a=commitdiff_plain;h=9e4791171cd6dd0185adffe50a2c5b65341c0a16 0029171: Foundation Classes - C signal handler does not work on MinGW 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. --- diff --git a/adm/cmake/occt_defs_flags.cmake b/adm/cmake/occt_defs_flags.cmake index b9389741ce..41db64ac96 100644 --- a/adm/cmake/occt_defs_flags.cmake +++ b/adm/cmake/occt_defs_flags.cmake @@ -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") diff --git a/src/OSD/OSD_signal.cxx b/src/OSD/OSD_signal.cxx index caeab21069..30482d4da1 100644 --- a/src/OSD/OSD_signal.cxx +++ b/src/OSD/OSD_signal.cxx @@ -65,10 +65,9 @@ #include 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 ***"); } }