1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
16 #include <OSD_Exception_CTRL_BREAK.hxx>
17 #include <Standard_DivideByZero.hxx>
18 #include <Standard_Overflow.hxx>
19 #include <Standard_Assert.hxx>
21 static OSD_SignalMode OSD_WasSetSignal = OSD_SignalMode_AsIs;
23 //=======================================================================
24 //function : SignalMode
26 //=======================================================================
27 OSD_SignalMode OSD::SignalMode()
29 return OSD_WasSetSignal;
33 //---------------------------- Windows NT System --------------------------------
45 #ifndef STATUS_FLOAT_MULTIPLE_FAULTS
47 #define STATUS_FLOAT_MULTIPLE_FAULTS (0xC00002B4L)
48 #define STATUS_FLOAT_MULTIPLE_TRAPS (0xC00002B5L)
51 #include <OSD_Exception_ACCESS_VIOLATION.hxx>
52 #include <OSD_Exception_ARRAY_BOUNDS_EXCEEDED.hxx>
53 #include <OSD_Exception_ILLEGAL_INSTRUCTION.hxx>
54 #include <OSD_Exception_IN_PAGE_ERROR.hxx>
55 #include <OSD_Exception_INT_DIVIDE_BY_ZERO.hxx>
56 #include <OSD_Exception_INT_OVERFLOW.hxx>
57 #include <OSD_Exception_INVALID_DISPOSITION.hxx>
58 #include <OSD_Exception_NONCONTINUABLE_EXCEPTION.hxx>
59 #include <OSD_Exception_PRIV_INSTRUCTION.hxx>
60 #include <OSD_Exception_STACK_OVERFLOW.hxx>
61 #include <OSD_Exception_STATUS_NO_MEMORY.hxx>
63 #include <OSD_Environment.hxx>
64 #include <Standard_Underflow.hxx>
65 #include <Standard_ProgramError.hxx>
66 #include <Standard_Mutex.hxx>
68 #include <OSD_WNT.hxx>
79 static Standard_Boolean fCtrlBrk;
81 static Standard_Boolean fMsgBox;
83 // used to forbid simultaneous execution of setting / executing handlers
84 static Standard_Mutex THE_SIGNAL_MUTEX;
86 static LONG __fastcall _osd_raise ( DWORD, LPSTR );
87 static BOOL WINAPI _osd_ctrl_break_handler ( DWORD );
89 #if ! defined(OCCT_UWP) && !defined(__MINGW32__) && !defined(__CYGWIN32__)
90 static Standard_Boolean fDbgLoaded;
91 static LONG _osd_debug ( void );
94 # define _OSD_FPX ( _EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW )
96 #ifdef OCC_CONVERT_SIGNALS
97 #define THROW_OR_JUMP(Type,Message) Type::NewInstance(Message)->Jump()
99 #define THROW_OR_JUMP(Type,Message) throw Type(Message)
102 //=======================================================================
103 //function : CallHandler
105 //=======================================================================
106 static LONG CallHandler (DWORD dwExceptionCode,
107 ptrdiff_t ExceptionInformation1,
108 ptrdiff_t ExceptionInformation0)
110 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
112 static wchar_t buffer[2048];
118 // std::cout << "CallHandler " << dwExceptionCode << std::endl ;
119 switch ( dwExceptionCode ) {
120 case EXCEPTION_FLT_DENORMAL_OPERAND:
121 // std::cout << "CallHandler : EXCEPTION_FLT_DENORMAL_OPERAND:" << std::endl ;
122 StringCchCopyW (buffer, _countof(buffer), L"FLT DENORMAL OPERAND");
125 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
126 // std::cout << "CallHandler : EXCEPTION_FLT_DIVIDE_BY_ZERO:" << std::endl ;
127 StringCchCopyW (buffer, _countof(buffer), L"FLT DIVIDE BY ZERO");
130 case EXCEPTION_FLT_INEXACT_RESULT:
131 // std::cout << "CallHandler : EXCEPTION_FLT_INEXACT_RESULT:" << std::endl ;
132 StringCchCopyW (buffer, _countof(buffer), L"FLT INEXACT RESULT");
135 case EXCEPTION_FLT_INVALID_OPERATION:
136 // std::cout << "CallHandler : EXCEPTION_FLT_INVALID_OPERATION:" << std::endl ;
137 StringCchCopyW (buffer, _countof(buffer), L"FLT INVALID OPERATION");
140 case EXCEPTION_FLT_OVERFLOW:
141 // std::cout << "CallHandler : EXCEPTION_FLT_OVERFLOW:" << std::endl ;
142 StringCchCopyW (buffer, _countof(buffer), L"FLT OVERFLOW");
145 case EXCEPTION_FLT_STACK_CHECK:
146 // std::cout << "CallHandler : EXCEPTION_FLT_STACK_CHECK:" << std::endl ;
147 StringCchCopyW (buffer, _countof(buffer), L"FLT STACK CHECK");
150 case EXCEPTION_FLT_UNDERFLOW:
151 // std::cout << "CallHandler : EXCEPTION_FLT_UNDERFLOW:" << std::endl ;
152 StringCchCopyW (buffer, _countof(buffer), L"FLT UNDERFLOW");
155 case STATUS_FLOAT_MULTIPLE_TRAPS:
156 // std::cout << "CallHandler : EXCEPTION_FLT_UNDERFLOW:" << std::endl ;
157 StringCchCopyW (buffer, _countof(buffer), L"FLT MULTIPLE TRAPS (possible overflow in conversion of double to integer)");
160 case STATUS_FLOAT_MULTIPLE_FAULTS:
161 // std::cout << "CallHandler : EXCEPTION_FLT_UNDERFLOW:" << std::endl ;
162 StringCchCopyW (buffer, _countof(buffer), L"FLT MULTIPLE FAULTS");
165 case STATUS_NO_MEMORY:
166 // std::cout << "CallHandler : STATUS_NO_MEMORY:" << std::endl ;
167 THROW_OR_JUMP (OSD_Exception_STATUS_NO_MEMORY, "MEMORY ALLOCATION ERROR ( no room in the process heap )");
169 case EXCEPTION_ACCESS_VIOLATION:
170 // std::cout << "CallHandler : EXCEPTION_ACCESS_VIOLATION:" << std::endl ;
171 StringCchPrintfW (buffer, _countof(buffer), L"%s%s%s0x%.8p%s%s%s", L"ACCESS VIOLATION",
172 fMsgBox ? L"\n" : L" ", L"at address ",
173 ExceptionInformation1 ,
175 ExceptionInformation0 ? L"WRITE" : L"READ",
178 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
179 // std::cout << "CallHandler : EXCEPTION_ARRAY_BOUNDS_EXCEEDED:" << std::endl ;
180 StringCchCopyW (buffer, _countof(buffer), L"ARRAY BOUNDS EXCEEDED");
182 case EXCEPTION_DATATYPE_MISALIGNMENT:
183 // std::cout << "CallHandler : EXCEPTION_DATATYPE_MISALIGNMENT:" << std::endl ;
184 StringCchCopyW (buffer, _countof(buffer), L"DATATYPE MISALIGNMENT");
187 case EXCEPTION_ILLEGAL_INSTRUCTION:
188 // std::cout << "CallHandler : EXCEPTION_ILLEGAL_INSTRUCTION:" << std::endl ;
189 StringCchCopyW (buffer, _countof(buffer), L"ILLEGAL INSTRUCTION");
192 case EXCEPTION_IN_PAGE_ERROR:
193 // std::cout << "CallHandler : EXCEPTION_IN_PAGE_ERROR:" << std::endl ;
194 StringCchCopyW (buffer, _countof(buffer), L"IN_PAGE ERROR");
197 case EXCEPTION_INT_DIVIDE_BY_ZERO:
198 // std::cout << "CallHandler : EXCEPTION_INT_DIVIDE_BY_ZERO:" << std::endl ;
199 StringCchCopyW (buffer, _countof(buffer), L"INTEGER DIVISION BY ZERO");
202 case EXCEPTION_INT_OVERFLOW:
203 // std::cout << "CallHandler : EXCEPTION_INT_OVERFLOW:" << std::endl ;
204 StringCchCopyW (buffer, _countof(buffer), L"INTEGER OVERFLOW");
207 case EXCEPTION_INVALID_DISPOSITION:
208 // std::cout << "CallHandler : EXCEPTION_INVALID_DISPOSITION:" << std::endl ;
209 StringCchCopyW (buffer, _countof(buffer), L"INVALID DISPOSITION");
212 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
213 // std::cout << "CallHandler : EXCEPTION_NONCONTINUABLE_EXCEPTION:" << std::endl ;
214 StringCchCopyW (buffer, _countof(buffer), L"NONCONTINUABLE EXCEPTION");
217 case EXCEPTION_PRIV_INSTRUCTION:
218 // std::cout << "CallHandler : EXCEPTION_PRIV_INSTRUCTION:" << std::endl ;
219 StringCchCopyW (buffer, _countof(buffer), L"PRIVELEGED INSTRUCTION ENCOUNTERED");
222 case EXCEPTION_STACK_OVERFLOW:
223 // std::cout << "CallHandler : EXCEPTION_STACK_OVERFLOW:" << std::endl ;
224 #if defined( _MSC_VER ) && ( _MSC_VER >= 1300 ) && !defined(OCCT_UWP)
225 // try recovering from stack overflow: available in MS VC++ 7.0
226 if (!_resetstkoflw())
227 StringCchCopyW (buffer, _countof(buffer), L"Unrecoverable STACK OVERFLOW");
230 StringCchCopyW (buffer, _countof(buffer), L"STACK OVERFLOW");
234 StringCchPrintfW (buffer, _countof(buffer), L"unknown exception code 0x%x, params 0x%p 0x%p",
235 dwExceptionCode, ExceptionInformation1, ExceptionInformation0 );
239 // reset FPE state (before message box, otherwise it may fail to show up)
241 OSD::SetFloatingSignal (Standard_True);
244 #if ! defined(OCCT_UWP) && !defined(__MINGW32__) && !defined(__CYGWIN32__)
245 // provide message to the user with possibility to stop
247 StringCchLengthW (buffer, _countof(buffer),&idx);
248 if ( idx && fMsgBox && dwExceptionCode != EXCEPTION_NONCONTINUABLE_EXCEPTION ) {
249 MessageBeep ( MB_ICONHAND );
250 int aChoice = ::MessageBoxW (0, buffer, L"OCCT Exception Handler", MB_ABORTRETRYIGNORE | MB_ICONSTOP);
251 if (aChoice == IDRETRY)
255 } else if (aChoice == IDABORT)
261 WideCharToMultiByte(CP_UTF8, 0, buffer, -1, aBufferA, sizeof(aBufferA), NULL, NULL);
262 return _osd_raise(dwExceptionCode, aBufferA);
265 //=======================================================================
266 //function : SIGWntHandler
267 //purpose : Will only be used if user calls ::raise() function with
268 // signal type set in OSD::SetSignal() - SIGSEGV, SIGFPE, SIGILL
269 // (the latter will likely be removed in the future)
270 //=======================================================================
271 static void SIGWntHandler (int signum, int sub_code)
273 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
276 if ( signal( signum , (void(*)(int))SIGWntHandler ) == SIG_ERR )
277 std::cout << "signal error" << std::endl ;
280 CallHandler( EXCEPTION_FLT_INVALID_OPERATION ,0,0) ;
283 CallHandler( EXCEPTION_FLT_DENORMAL_OPERAND ,0,0) ;
285 case _FPE_ZERODIVIDE :
286 CallHandler( EXCEPTION_FLT_DIVIDE_BY_ZERO ,0,0) ;
289 CallHandler( EXCEPTION_FLT_OVERFLOW ,0,0) ;
291 case _FPE_UNDERFLOW :
292 CallHandler( EXCEPTION_FLT_UNDERFLOW ,0,0) ;
295 CallHandler( EXCEPTION_FLT_INEXACT_RESULT ,0,0) ;
298 std::cout << "SIGWntHandler(default) -> throw Standard_NumericError(\"Floating Point Error\");" << std::endl;
299 THROW_OR_JUMP (Standard_NumericError, "Floating Point Error");
304 if ( signal( signum, (void(*)(int))SIGWntHandler ) == SIG_ERR )
305 std::cout << "signal error" << std::endl ;
306 CallHandler( EXCEPTION_ACCESS_VIOLATION ,0,0) ;
309 if ( signal( signum, (void(*)(int))SIGWntHandler ) == SIG_ERR )
310 std::cout << "signal error" << std::endl ;
311 CallHandler( EXCEPTION_ILLEGAL_INSTRUCTION ,0,0) ;
314 std::cout << "SIGWntHandler unexpected signal : " << signum << std::endl ;
322 //=======================================================================
323 //function : TranslateSE
324 //purpose : Translate Structural Exceptions into C++ exceptions
325 // Will be used when user's code is compiled with /EHa option
326 //=======================================================================
328 // If this file compiled with the default MSVC options for exception
329 // handling (/GX or /EHsc) then the following warning is issued:
330 // warning C4535: calling _set_se_translator() requires /EHa
331 // However it is correctly inserted and used when user's code compiled with /EHa.
332 // So, here we disable the warning.
333 #pragma warning (disable:4535)
335 static void TranslateSE( unsigned int theCode, EXCEPTION_POINTERS* theExcPtr )
337 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
338 ptrdiff_t info1 = 0, info0 = 0;
340 info1 = theExcPtr->ExceptionRecord->ExceptionInformation[1];
341 info0 = theExcPtr->ExceptionRecord->ExceptionInformation[0];
343 CallHandler(theCode, info1, info0);
347 //=======================================================================
348 //function : WntHandler
349 //purpose : Will be used when user's code is compiled with /EHs
350 // option and unless user sets his own exception handler with
351 // ::SetUnhandledExceptionFilter().
352 //=======================================================================
353 static LONG WINAPI WntHandler (EXCEPTION_POINTERS *lpXP)
355 DWORD dwExceptionCode = lpXP->ExceptionRecord->ExceptionCode;
357 return CallHandler (dwExceptionCode,
358 lpXP->ExceptionRecord->ExceptionInformation[1],
359 lpXP->ExceptionRecord->ExceptionInformation[0]);
362 //=======================================================================
363 //function : SetFloatingSignal
365 //=======================================================================
366 void OSD::SetFloatingSignal (Standard_Boolean theFloatingSignal)
371 // Note: zero bit means exception will be raised
372 _controlfp (theFloatingSignal ? 0 : _OSD_FPX, _OSD_FPX);
375 //=======================================================================
376 //function : ToCatchFloatingSignals
378 //=======================================================================
379 Standard_Boolean OSD::ToCatchFloatingSignals()
381 // return true if at least one of bits within _OSD_FPX
382 // is unset, which means relevant FPE will raise exception
383 int aControlWord = _controlfp (0, 0);
384 return (_OSD_FPX & ~aControlWord) != 0;
387 //=======================================================================
388 //function : SetThreadLocalSignal
390 //=======================================================================
391 void OSD::SetThreadLocalSignal (OSD_SignalMode theSignalMode,
392 Standard_Boolean theFloatingSignal)
395 _se_translator_function aPreviousFunc = NULL;
396 if (theSignalMode == OSD_SignalMode_Set || theSignalMode == OSD_SignalMode_SetUnhandled)
397 aPreviousFunc = _set_se_translator(TranslateSE);
398 if (theSignalMode == OSD_SignalMode_Unset || (theSignalMode == OSD_SignalMode_SetUnhandled && aPreviousFunc != NULL))
399 _set_se_translator(aPreviousFunc);
403 SetFloatingSignal (theFloatingSignal);
406 //=======================================================================
407 //function : SetSignal
409 //=======================================================================
410 void OSD::SetSignal (OSD_SignalMode theSignalMode,
411 Standard_Boolean theFloatingSignal)
413 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
414 OSD_WasSetSignal = theSignalMode;
416 #if !defined(OCCT_UWP) || defined(NTDDI_WIN10_TH2)
417 OSD_Environment env ("CSF_DEBUG_MODE");
418 TCollection_AsciiString val = env.Value();
421 std::cout << "Environment variable CSF_DEBUG_MODE setted.\n";
422 fMsgBox = Standard_True;
426 fMsgBox = Standard_False;
429 // Set exception handler (ignored when running under debugger). It will be used in most cases
430 // when user's code is compiled with /EHs
431 // Replaces the existing top-level exception filter for all existing and all future threads
432 // in the calling process
434 LPTOP_LEVEL_EXCEPTION_FILTER aPreviousFunc = NULL;
435 if (theSignalMode == OSD_SignalMode_Set || theSignalMode == OSD_SignalMode_SetUnhandled)
437 aPreviousFunc = ::SetUnhandledExceptionFilter(WntHandler);
439 if (theSignalMode == OSD_SignalMode_Unset || (theSignalMode == OSD_SignalMode_SetUnhandled && aPreviousFunc != NULL))
441 ::SetUnhandledExceptionFilter(aPreviousFunc);
444 #endif // NTDDI_WIN10_TH2
446 // Signal handlers will only be used when function ::raise() is called
448 const int aSignalTypes[NBSIG] = { SIGSEGV, SIGILL, SIGFPE };
449 for (int i = 0; i < NBSIG; ++i)
451 typedef void (*SignalFuncType)(int); // same as _crt_signal_t available since vc14
452 SignalFuncType aPreviousFunc = SIG_DFL;
453 if (theSignalMode == OSD_SignalMode_Set || theSignalMode == OSD_SignalMode_SetUnhandled)
455 aPreviousFunc = signal(aSignalTypes[i], (SignalFuncType)SIGWntHandler);
457 if (theSignalMode == OSD_SignalMode_Unset ||
458 (theSignalMode == OSD_SignalMode_SetUnhandled && aPreviousFunc != SIG_DFL && aPreviousFunc != SIG_ERR))
460 aPreviousFunc = signal(aSignalTypes[i], aPreviousFunc);
462 Standard_ASSERT(aPreviousFunc != SIG_ERR, "signal() failed", std::cout << "OSD::SetSignal(): signal() returns SIG_ERR");
465 // Set Ctrl-C and Ctrl-Break handler
466 fCtrlBrk = Standard_False;
468 if (theSignalMode == OSD_SignalMode_Set || theSignalMode == OSD_SignalMode_SetUnhandled)
470 SetConsoleCtrlHandler(&_osd_ctrl_break_handler, true);
472 else if (theSignalMode == OSD_SignalMode_Unset)
474 SetConsoleCtrlHandler(&_osd_ctrl_break_handler, false);
478 SetThreadLocalSignal (theSignalMode, theFloatingSignal);
481 //============================================================================
483 //============================================================================
484 void OSD::ControlBreak () {
486 fCtrlBrk = Standard_False;
487 throw OSD_Exception_CTRL_BREAK ( "*** INTERRUPT ***" );
489 } // end OSD :: ControlBreak
492 //============================================================================
493 //==== _osd_ctrl_break_handler
494 //============================================================================
495 static BOOL WINAPI _osd_ctrl_break_handler ( DWORD dwCode ) {
496 if ( dwCode == CTRL_C_EVENT || dwCode == CTRL_BREAK_EVENT ) {
497 MessageBeep ( MB_ICONEXCLAMATION );
498 fCtrlBrk = Standard_True;
503 } // end _osd_ctrl_break_handler
506 //============================================================================
508 //============================================================================
509 static LONG __fastcall _osd_raise ( DWORD dwCode, LPSTR msg )
511 if (msg[0] == '\x03') ++msg;
515 case EXCEPTION_ACCESS_VIOLATION:
516 THROW_OR_JUMP (OSD_Exception_ACCESS_VIOLATION, msg);
518 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
519 THROW_OR_JUMP (OSD_Exception_ARRAY_BOUNDS_EXCEEDED, msg);
521 case EXCEPTION_DATATYPE_MISALIGNMENT:
522 THROW_OR_JUMP (Standard_ProgramError, msg);
524 case EXCEPTION_ILLEGAL_INSTRUCTION:
525 THROW_OR_JUMP (OSD_Exception_ILLEGAL_INSTRUCTION, msg);
527 case EXCEPTION_IN_PAGE_ERROR:
528 THROW_OR_JUMP (OSD_Exception_IN_PAGE_ERROR, msg);
530 case EXCEPTION_INT_DIVIDE_BY_ZERO:
531 THROW_OR_JUMP (Standard_DivideByZero, msg);
533 case EXCEPTION_INT_OVERFLOW:
534 THROW_OR_JUMP (OSD_Exception_INT_OVERFLOW, msg);
536 case EXCEPTION_INVALID_DISPOSITION:
537 THROW_OR_JUMP (OSD_Exception_INVALID_DISPOSITION, msg);
539 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
540 THROW_OR_JUMP (OSD_Exception_NONCONTINUABLE_EXCEPTION, msg);
542 case EXCEPTION_PRIV_INSTRUCTION:
543 THROW_OR_JUMP (OSD_Exception_PRIV_INSTRUCTION, msg);
545 case EXCEPTION_STACK_OVERFLOW:
546 THROW_OR_JUMP (OSD_Exception_STACK_OVERFLOW, msg);
548 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
549 THROW_OR_JUMP (Standard_DivideByZero, msg);
551 case EXCEPTION_FLT_STACK_CHECK:
552 case EXCEPTION_FLT_OVERFLOW:
553 THROW_OR_JUMP (Standard_Overflow, msg);
555 case EXCEPTION_FLT_UNDERFLOW:
556 THROW_OR_JUMP (Standard_Underflow, msg);
558 case EXCEPTION_FLT_INVALID_OPERATION:
559 case EXCEPTION_FLT_DENORMAL_OPERAND:
560 case EXCEPTION_FLT_INEXACT_RESULT:
561 case STATUS_FLOAT_MULTIPLE_TRAPS:
562 case STATUS_FLOAT_MULTIPLE_FAULTS:
563 THROW_OR_JUMP (Standard_NumericError, msg);
568 return EXCEPTION_EXECUTE_HANDLER;
571 #if ! defined(OCCT_UWP) && !defined(__MINGW32__) && !defined(__CYGWIN32__)
572 //============================================================================
574 //============================================================================
575 LONG _osd_debug ( void ) {
582 HANDLE hEvent = INVALID_HANDLE_VALUE;
585 TCHAR keyValue[ MAX_PATH ];
586 TCHAR cmdLine[ MAX_PATH ];
587 SECURITY_ATTRIBUTES sa;
588 PROCESS_INFORMATION pi;
595 TEXT( "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug" ),
600 dwValueLen = sizeof ( keyValue );
602 if ( RegQueryValueEx (
603 hKey, TEXT( "Debugger" ), NULL, &dwKeyType, ( unsigned char* )keyValue, &dwValueLen
607 sa.nLength = sizeof ( SECURITY_ATTRIBUTES );
608 sa.lpSecurityDescriptor = NULL;
609 sa.bInheritHandle = TRUE;
611 if ( ( hEvent = CreateEvent ( &sa, TRUE, FALSE, NULL ) ) == NULL ) __leave;
613 StringCchPrintf(cmdLine, _countof(cmdLine), keyValue, GetCurrentProcessId(), hEvent);
615 ZeroMemory ( &si, sizeof ( STARTUPINFO ) );
617 si.cb = sizeof ( STARTUPINFO );
618 si.dwFlags = STARTF_FORCEONFEEDBACK;
620 // std::cout << "_osd_debug -> CreateProcess" << std::endl ;
621 if ( !CreateProcess (
622 NULL, cmdLine, NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE,
627 // std::cout << "_osd_debug -> WaitForSingleObject " << std::endl ;
628 WaitForSingleObject ( hEvent, INFINITE );
629 // std::cout << "_osd_debug <- WaitForSingleObject -> CloseHandle " << std::endl ;
631 CloseHandle ( pi.hProcess );
632 CloseHandle ( pi.hThread );
634 // std::cout << "_osd_debug fDbgLoaded " << std::endl ;
641 // std::cout << "_osd_debug -> CloseHandle(hKey) " << std::endl ;
642 if ( hKey != INVALID_HANDLE_VALUE ) CloseHandle ( hKey );
643 // std::cout << "_osd_debug -> CloseHandle(hEvent) " << std::endl ;
644 if ( hEvent != INVALID_HANDLE_VALUE ) CloseHandle ( hEvent );
645 // std::cout << "_osd_debug end __finally " << std::endl ;
651 action = fDbgLoaded ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER;
652 // std::cout << "_osd_debug return " << action << " EXCEPTION_CONTINUE_EXECUTION("
653 // << EXCEPTION_CONTINUE_EXECUTION << ")" << std::endl ;
657 #endif /* ! OCCT_UWP && ! __CYGWIN__ && ! __MINGW32__ */
661 //---------- All Systems except Windows NT : ----------------------------------
665 #include <OSD_WhoAmI.hxx>
666 #include <OSD_SIGHUP.hxx>
667 #include <OSD_SIGINT.hxx>
668 #include <OSD_SIGQUIT.hxx>
669 #include <OSD_SIGILL.hxx>
670 #include <OSD_SIGKILL.hxx>
671 #include <OSD_SIGBUS.hxx>
672 #include <OSD_SIGSEGV.hxx>
673 #include <OSD_SIGSYS.hxx>
674 #include <Standard_NumericError.hxx>
676 #include <Standard_ErrorHandler.hxx>
686 // variable signalling that Control-C has been pressed (SIGINT signal)
687 static Standard_Boolean fCtrlBrk;
689 //const OSD_WhoAmI Iam = OSD_WPackage;
691 typedef void (ACT_SIGIO_HANDLER)(void) ;
692 ACT_SIGIO_HANDLER *ADR_ACT_SIGIO_HANDLER = NULL ;
699 # include <sys/siginfo.h>
702 typedef void (* SIG_PFV) (int);
706 #if !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__)
707 #include <sys/signal.h>
710 # define _OSD_FPX (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW)
712 //============================================================================
714 //==== Catche the differents signals:
715 //==== 1- The Fatal signals, which cause the end of process:
716 //==== 2- The exceptions which are "signaled" by Raise.
717 //==== The Fatal Signals:
718 //==== SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGKILL, SIGBUS, SIGSYS
719 //==== The Exceptions:
721 //==== (SUN versions)
722 //==== FPE_INTOVF_TRAP // ..... integer overflow
723 //==== FPE_INTDIV_TRAP // ..... integer divide by zero
724 //==== FPE_FLTINEX_TRAP // ..... [floating inexact result]
725 //==== FPE_FLTDIV_TRAP // ..... [floating divide by zero]
726 //==== FPE_FLTUND_TRAP // ..... [floating underflow]
727 //==== FPE_FLTOPER_TRAP // ..... [floating inexact result]
728 //==== FPE_FLTOVF_TRAP // ..... [floating overflow]
729 //==== SIGSEGV is handled by "SegvHandler()"
730 //============================================================================
732 static void Handler (const int theSignal, siginfo_t */*theSigInfo*/, const Standard_Address /*theContext*/)
734 static void Handler (const int theSignal)
737 struct sigaction oldact, act;
738 // re-install the signal
739 if ( ! sigaction (theSignal, NULL, &oldact) ) {
740 // std::cout << " signal is " << theSignal << " handler is " << oldact.sa_handler << std::endl;
741 if (sigaction (theSignal, &oldact, &act)) perror ("sigaction");
744 perror ("sigaction");
747 // std::cout << "OSD::Handler: signal " << (int) theSignal << " occured inside a try block " << std::endl ;
748 if ( ADR_ACT_SIGIO_HANDLER != NULL )
749 (*ADR_ACT_SIGIO_HANDLER)() ;
755 OSD_SIGHUP::NewInstance("SIGHUP 'hangup' detected.")->Jump();
759 // For safe handling of Control-C as stop event, arm a variable but do not
760 // generate longjump (we are out of context anyway)
761 fCtrlBrk = Standard_True;
762 // OSD_SIGINT::NewInstance("SIGINT 'interrupt' detected.")->Jump();
766 OSD_SIGQUIT::NewInstance("SIGQUIT 'quit' detected.")->Jump();
770 OSD_SIGILL::NewInstance("SIGILL 'illegal instruction' detected.")->Jump();
774 OSD_SIGKILL::NewInstance("SIGKILL 'kill' detected.")->Jump();
778 sigaddset(&set, SIGBUS);
779 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
780 OSD_SIGBUS::NewInstance("SIGBUS 'bus error' detected.")->Jump();
784 OSD_SIGSEGV::NewInstance("SIGSEGV 'segmentation violation' detected.")->Jump();
789 OSD_SIGSYS::NewInstance("SIGSYS 'bad argument to system call' detected.")->Jump();
794 sigaddset(&set, SIGFPE);
795 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
797 OSD::SetFloatingSignal (Standard_True);
799 #if (!defined (__sun)) && (!defined(SOLARIS))
800 Standard_NumericError::NewInstance("SIGFPE Arithmetic exception detected")->Jump();
805 switch(aSigInfo->si_code) {
806 case FPE_FLTDIV_TRAP :
807 Standard_DivideByZero::NewInstance("Floating Divide By Zero")->Jump();
809 case FPE_INTDIV_TRAP :
810 Standard_DivideByZero::NewInstance("Integer Divide By Zero")->Jump();
812 case FPE_FLTOVF_TRAP :
813 Standard_Overflow::NewInstance("Floating Overflow")->Jump();
815 case FPE_INTOVF_TRAP :
816 Standard_Overflow::NewInstance("Integer Overflow")->Jump();
818 case FPE_FLTUND_TRAP :
819 Standard_NumericError::NewInstance("Floating Underflow")->Jump();
821 case FPE_FLTRES_TRAP:
822 Standard_NumericError::NewInstance("Floating Point Inexact Result")->Jump();
824 case FPE_FLTINV_TRAP :
825 Standard_NumericError::NewInstance("Invalid Floating Point Operation")->Jump();
828 Standard_NumericError::NewInstance("Numeric Error")->Jump();
832 Standard_NumericError::NewInstance("SIGFPE Arithmetic exception detected")->Jump();
838 std::cout << "Unexpected signal " << theSignal << std::endl ;
844 //============================================================================
846 //============================================================================
849 static void SegvHandler(const int theSignal,
851 const Standard_Address theContext)
853 (void)theSignal; // silence GCC warnings
856 // std::cout << "OSD::SegvHandler activated(SA_SIGINFO)" << std::endl ;
860 sigaddset(&set, SIGSEGV);
861 sigprocmask (SIG_UNBLOCK, &set, NULL) ;
862 void *address = ip->si_addr ;
865 sprintf(Msg,"SIGSEGV 'segmentation violation' detected. Address %lx",
867 OSD_SIGSEGV::NewInstance(Msg)->Jump();
872 std::cout << "Wrong undefined address." << std::endl ;
878 #elif defined (_hpux) || defined(HPUX)
879 // Not ACTIVE ? SA_SIGINFO is defined on SUN, OSF, SGI and HP (and Linux) !
880 // pour version 09.07
882 static void SegvHandler(const int theSignal,
884 const Standard_Address theContext)
886 unsigned long Space ;
887 unsigned long Offset ;
890 if ( theContext != NULL ) {
891 Space = ((struct sigcontext *)theContext)->sc_sl.sl_ss.ss_cr20 ;
892 Offset = ((struct sigcontext *)theContext)->sc_sl.sl_ss.ss_cr21 ;
893 // std::cout << "Wrong address = " << hex(Offset) << std::endl ;
895 sprintf(Msg,"SIGSEGV 'segmentation violation' detected. Address %lx",Offset) ;
896 OSD_SIGSEGV::Jump(Msg);
897 // scp->sc_pcoq_head = scp->sc_pcoq_tail ; Permettrait de continuer a
898 // scp->sc_pcoq_tail = scp->sc_pcoq_tail + 0x4 ; l'intruction suivant le segv.
903 std::cout << "Wrong undefined address." << std::endl ;
911 //=======================================================================
912 //function : SetFloatingSignal
914 //=======================================================================
915 void OSD::SetFloatingSignal (Standard_Boolean theFloatingSignal)
917 #if defined (__linux__)
918 feclearexcept (FE_ALL_EXCEPT);
919 if (theFloatingSignal)
921 feenableexcept (_OSD_FPX);
925 fedisableexcept (_OSD_FPX);
927 #elif defined (__sun) || defined (SOLARIS)
929 sigfpe_handler_type anFpeHandler = (theFloatingSignal ? (sigfpe_handler_type)Handler : NULL);
930 aSunStat = ieee_handler ("set", "invalid", anFpeHandler);
931 aSunStat = ieee_handler ("set", "division", anFpeHandler) || aSunStat;
932 aSunStat = ieee_handler ("set", "overflow", anFpeHandler) || aSunStat;
936 std::cerr << "ieee_handler does not work !!! KO\n";
940 (void)theFloatingSignal;
944 //=======================================================================
945 //function : ToCatchFloatingSignals
947 //=======================================================================
948 Standard_Boolean OSD::ToCatchFloatingSignals()
950 #if defined (__linux__)
951 return (fegetexcept() & _OSD_FPX) != 0;
953 return Standard_False;
957 //=======================================================================
958 //function : SetThreadLocalSignal
960 //=======================================================================
961 void OSD::SetThreadLocalSignal (OSD_SignalMode /*theSignalMode*/,
962 Standard_Boolean theFloatingSignal)
964 SetFloatingSignal (theFloatingSignal);
967 //============================================================================
969 //==== Set the differents signals:
970 //============================================================================
972 void OSD::SetSignal (OSD_SignalMode theSignalMode,
973 Standard_Boolean theFloatingSignal)
975 SetFloatingSignal (theFloatingSignal);
977 OSD_WasSetSignal = theSignalMode;
978 if (theSignalMode == OSD_SignalMode_AsIs)
980 return; // nothing to be done with signal handlers
983 // Prepare signal descriptors
984 struct sigaction anActSet, anActDfl, anActOld;
985 sigemptyset(&anActSet.sa_mask);
986 sigemptyset(&anActDfl.sa_mask);
987 sigemptyset(&anActOld.sa_mask);
989 anActSet.sa_flags = anActDfl.sa_flags = anActOld.sa_flags = SA_RESTART;
991 anActSet.sa_flags = anActDfl.sa_flags = anActOld.sa_flags = 0;
994 anActSet.sa_flags = anActSet.sa_flags | SA_SIGINFO;
995 anActSet.sa_sigaction = Handler;
997 anActSet.sa_handler = Handler;
999 anActDfl.sa_handler = SIG_DFL;
1001 // Set signal handlers; NB: SIGSEGV must be the last one!
1002 const int NBSIG = 8;
1003 const int aSignalTypes[NBSIG] = { SIGFPE, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGBUS, SIGSYS, SIGSEGV };
1004 for (int i = 0; i < NBSIG; ++i)
1006 // SIGSEGV has special handler
1007 if (aSignalTypes[i] == SIGSEGV)
1010 anActSet.sa_sigaction = /*(void(*)(int, siginfo_t *, void*))*/ SegvHandler;
1012 anActSet.sa_handler = /*(SIG_PFV)*/ SegvHandler;
1016 // set handler according to specified mode and current handler
1018 if (theSignalMode == OSD_SignalMode_Set || theSignalMode == OSD_SignalMode_SetUnhandled)
1020 retcode = sigaction (aSignalTypes[i], &anActSet, &anActOld);
1022 else if (theSignalMode == OSD_SignalMode_Unset)
1024 retcode = sigaction (aSignalTypes[i], &anActDfl, &anActOld);
1026 if (theSignalMode == OSD_SignalMode_SetUnhandled && retcode == 0 && anActOld.sa_handler != SIG_DFL)
1028 retcode = sigaction (aSignalTypes[i], &anActOld, &anActOld);
1030 Standard_ASSERT(retcode == 0, "sigaction() failed", std::cout << "OSD::SetSignal(): sigaction() failed for " << aSignalTypes[i] << std::endl);
1034 //============================================================================
1036 //============================================================================
1038 void OSD :: ControlBreak ()
1041 fCtrlBrk = Standard_False;
1042 throw OSD_Exception_CTRL_BREAK ("*** INTERRUPT ***");