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 #include <Standard_WarningDisableFunctionCast.hxx>
23 static OSD_SignalMode OSD_WasSetSignal = OSD_SignalMode_AsIs;
25 //=======================================================================
26 //function : SignalMode
28 //=======================================================================
29 OSD_SignalMode OSD::SignalMode()
31 return OSD_WasSetSignal;
35 //---------------------------- Windows NT System --------------------------------
47 #ifndef STATUS_FLOAT_MULTIPLE_FAULTS
49 #define STATUS_FLOAT_MULTIPLE_FAULTS (0xC00002B4L)
50 #define STATUS_FLOAT_MULTIPLE_TRAPS (0xC00002B5L)
53 #include <OSD_Exception_ACCESS_VIOLATION.hxx>
54 #include <OSD_Exception_ARRAY_BOUNDS_EXCEEDED.hxx>
55 #include <OSD_Exception_ILLEGAL_INSTRUCTION.hxx>
56 #include <OSD_Exception_IN_PAGE_ERROR.hxx>
57 #include <OSD_Exception_INT_DIVIDE_BY_ZERO.hxx>
58 #include <OSD_Exception_INT_OVERFLOW.hxx>
59 #include <OSD_Exception_INVALID_DISPOSITION.hxx>
60 #include <OSD_Exception_NONCONTINUABLE_EXCEPTION.hxx>
61 #include <OSD_Exception_PRIV_INSTRUCTION.hxx>
62 #include <OSD_Exception_STACK_OVERFLOW.hxx>
63 #include <OSD_Exception_STATUS_NO_MEMORY.hxx>
65 #include <OSD_Environment.hxx>
66 #include <Standard_Underflow.hxx>
67 #include <Standard_ProgramError.hxx>
68 #include <Standard_Mutex.hxx>
70 #include <OSD_WNT.hxx>
81 static Standard_Boolean fCtrlBrk;
83 static Standard_Boolean fMsgBox;
85 // used to forbid simultaneous execution of setting / executing handlers
86 static Standard_Mutex THE_SIGNAL_MUTEX;
88 static LONG __fastcall _osd_raise ( DWORD, LPSTR );
89 static BOOL WINAPI _osd_ctrl_break_handler ( DWORD );
91 #if ! defined(OCCT_UWP) && !defined(__MINGW32__) && !defined(__CYGWIN32__)
92 static Standard_Boolean fDbgLoaded;
93 static LONG _osd_debug ( void );
96 # define _OSD_FPX ( _EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW )
98 #ifdef OCC_CONVERT_SIGNALS
99 #define THROW_OR_JUMP(Type,Message) Type::NewInstance(Message)->Jump()
101 #define THROW_OR_JUMP(Type,Message) throw Type(Message)
104 //=======================================================================
105 //function : CallHandler
107 //=======================================================================
108 static LONG CallHandler (DWORD dwExceptionCode,
109 ptrdiff_t ExceptionInformation1,
110 ptrdiff_t ExceptionInformation0)
112 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
114 static wchar_t buffer[2048];
120 // std::cout << "CallHandler " << dwExceptionCode << std::endl ;
121 switch ( dwExceptionCode ) {
122 case EXCEPTION_FLT_DENORMAL_OPERAND:
123 // std::cout << "CallHandler : EXCEPTION_FLT_DENORMAL_OPERAND:" << std::endl ;
124 StringCchCopyW (buffer, _countof(buffer), L"FLT DENORMAL OPERAND");
127 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
128 // std::cout << "CallHandler : EXCEPTION_FLT_DIVIDE_BY_ZERO:" << std::endl ;
129 StringCchCopyW (buffer, _countof(buffer), L"FLT DIVIDE BY ZERO");
132 case EXCEPTION_FLT_INEXACT_RESULT:
133 // std::cout << "CallHandler : EXCEPTION_FLT_INEXACT_RESULT:" << std::endl ;
134 StringCchCopyW (buffer, _countof(buffer), L"FLT INEXACT RESULT");
137 case EXCEPTION_FLT_INVALID_OPERATION:
138 // std::cout << "CallHandler : EXCEPTION_FLT_INVALID_OPERATION:" << std::endl ;
139 StringCchCopyW (buffer, _countof(buffer), L"FLT INVALID OPERATION");
142 case EXCEPTION_FLT_OVERFLOW:
143 // std::cout << "CallHandler : EXCEPTION_FLT_OVERFLOW:" << std::endl ;
144 StringCchCopyW (buffer, _countof(buffer), L"FLT OVERFLOW");
147 case EXCEPTION_FLT_STACK_CHECK:
148 // std::cout << "CallHandler : EXCEPTION_FLT_STACK_CHECK:" << std::endl ;
149 StringCchCopyW (buffer, _countof(buffer), L"FLT STACK CHECK");
152 case EXCEPTION_FLT_UNDERFLOW:
153 // std::cout << "CallHandler : EXCEPTION_FLT_UNDERFLOW:" << std::endl ;
154 StringCchCopyW (buffer, _countof(buffer), L"FLT UNDERFLOW");
157 case STATUS_FLOAT_MULTIPLE_TRAPS:
158 // std::cout << "CallHandler : EXCEPTION_FLT_UNDERFLOW:" << std::endl ;
159 StringCchCopyW (buffer, _countof(buffer), L"FLT MULTIPLE TRAPS (possible overflow in conversion of double to integer)");
162 case STATUS_FLOAT_MULTIPLE_FAULTS:
163 // std::cout << "CallHandler : EXCEPTION_FLT_UNDERFLOW:" << std::endl ;
164 StringCchCopyW (buffer, _countof(buffer), L"FLT MULTIPLE FAULTS");
167 case STATUS_NO_MEMORY:
168 // std::cout << "CallHandler : STATUS_NO_MEMORY:" << std::endl ;
169 THROW_OR_JUMP (OSD_Exception_STATUS_NO_MEMORY, "MEMORY ALLOCATION ERROR ( no room in the process heap )");
171 case EXCEPTION_ACCESS_VIOLATION:
172 // std::cout << "CallHandler : EXCEPTION_ACCESS_VIOLATION:" << std::endl ;
173 StringCchPrintfW (buffer, _countof(buffer), L"%s%s%s0x%.8p%s%s%s", L"ACCESS VIOLATION",
174 fMsgBox ? L"\n" : L" ", L"at address ",
175 ExceptionInformation1 ,
177 ExceptionInformation0 ? L"WRITE" : L"READ",
180 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
181 // std::cout << "CallHandler : EXCEPTION_ARRAY_BOUNDS_EXCEEDED:" << std::endl ;
182 StringCchCopyW (buffer, _countof(buffer), L"ARRAY BOUNDS EXCEEDED");
184 case EXCEPTION_DATATYPE_MISALIGNMENT:
185 // std::cout << "CallHandler : EXCEPTION_DATATYPE_MISALIGNMENT:" << std::endl ;
186 StringCchCopyW (buffer, _countof(buffer), L"DATATYPE MISALIGNMENT");
189 case EXCEPTION_ILLEGAL_INSTRUCTION:
190 // std::cout << "CallHandler : EXCEPTION_ILLEGAL_INSTRUCTION:" << std::endl ;
191 StringCchCopyW (buffer, _countof(buffer), L"ILLEGAL INSTRUCTION");
194 case EXCEPTION_IN_PAGE_ERROR:
195 // std::cout << "CallHandler : EXCEPTION_IN_PAGE_ERROR:" << std::endl ;
196 StringCchCopyW (buffer, _countof(buffer), L"IN_PAGE ERROR");
199 case EXCEPTION_INT_DIVIDE_BY_ZERO:
200 // std::cout << "CallHandler : EXCEPTION_INT_DIVIDE_BY_ZERO:" << std::endl ;
201 StringCchCopyW (buffer, _countof(buffer), L"INTEGER DIVISION BY ZERO");
204 case EXCEPTION_INT_OVERFLOW:
205 // std::cout << "CallHandler : EXCEPTION_INT_OVERFLOW:" << std::endl ;
206 StringCchCopyW (buffer, _countof(buffer), L"INTEGER OVERFLOW");
209 case EXCEPTION_INVALID_DISPOSITION:
210 // std::cout << "CallHandler : EXCEPTION_INVALID_DISPOSITION:" << std::endl ;
211 StringCchCopyW (buffer, _countof(buffer), L"INVALID DISPOSITION");
214 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
215 // std::cout << "CallHandler : EXCEPTION_NONCONTINUABLE_EXCEPTION:" << std::endl ;
216 StringCchCopyW (buffer, _countof(buffer), L"NONCONTINUABLE EXCEPTION");
219 case EXCEPTION_PRIV_INSTRUCTION:
220 // std::cout << "CallHandler : EXCEPTION_PRIV_INSTRUCTION:" << std::endl ;
221 StringCchCopyW (buffer, _countof(buffer), L"PRIVELEGED INSTRUCTION ENCOUNTERED");
224 case EXCEPTION_STACK_OVERFLOW:
225 // std::cout << "CallHandler : EXCEPTION_STACK_OVERFLOW:" << std::endl ;
226 #if defined( _MSC_VER ) && ( _MSC_VER >= 1300 ) && !defined(OCCT_UWP)
227 // try recovering from stack overflow: available in MS VC++ 7.0
228 if (!_resetstkoflw())
229 StringCchCopyW (buffer, _countof(buffer), L"Unrecoverable STACK OVERFLOW");
232 StringCchCopyW (buffer, _countof(buffer), L"STACK OVERFLOW");
236 StringCchPrintfW (buffer, _countof(buffer), L"unknown exception code 0x%x, params 0x%p 0x%p",
237 dwExceptionCode, ExceptionInformation1, ExceptionInformation0 );
241 // reset FPE state (before message box, otherwise it may fail to show up)
243 OSD::SetFloatingSignal (Standard_True);
246 #if ! defined(OCCT_UWP) && !defined(__MINGW32__) && !defined(__CYGWIN32__)
247 // provide message to the user with possibility to stop
249 StringCchLengthW (buffer, _countof(buffer),&idx);
250 if ( idx && fMsgBox && dwExceptionCode != EXCEPTION_NONCONTINUABLE_EXCEPTION ) {
251 MessageBeep ( MB_ICONHAND );
252 int aChoice = ::MessageBoxW (0, buffer, L"OCCT Exception Handler", MB_ABORTRETRYIGNORE | MB_ICONSTOP);
253 if (aChoice == IDRETRY)
257 } else if (aChoice == IDABORT)
263 WideCharToMultiByte(CP_UTF8, 0, buffer, -1, aBufferA, sizeof(aBufferA), NULL, NULL);
264 return _osd_raise(dwExceptionCode, aBufferA);
267 //=======================================================================
268 //function : SIGWntHandler
269 //purpose : Will only be used if user calls ::raise() function with
270 // signal type set in OSD::SetSignal() - SIGSEGV, SIGFPE, SIGILL
271 // (the latter will likely be removed in the future)
272 //=======================================================================
273 static void SIGWntHandler (int signum, int sub_code)
275 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
278 if ( signal( signum , (void(*)(int))SIGWntHandler ) == SIG_ERR )
279 std::cout << "signal error" << std::endl ;
282 CallHandler( EXCEPTION_FLT_INVALID_OPERATION ,0,0) ;
285 CallHandler( EXCEPTION_FLT_DENORMAL_OPERAND ,0,0) ;
287 case _FPE_ZERODIVIDE :
288 CallHandler( EXCEPTION_FLT_DIVIDE_BY_ZERO ,0,0) ;
291 CallHandler( EXCEPTION_FLT_OVERFLOW ,0,0) ;
293 case _FPE_UNDERFLOW :
294 CallHandler( EXCEPTION_FLT_UNDERFLOW ,0,0) ;
297 CallHandler( EXCEPTION_FLT_INEXACT_RESULT ,0,0) ;
300 std::cout << "SIGWntHandler(default) -> throw Standard_NumericError(\"Floating Point Error\");" << std::endl;
301 THROW_OR_JUMP (Standard_NumericError, "Floating Point Error");
306 if ( signal( signum, (void(*)(int))SIGWntHandler ) == SIG_ERR )
307 std::cout << "signal error" << std::endl ;
308 CallHandler( EXCEPTION_ACCESS_VIOLATION ,0,0) ;
311 if ( signal( signum, (void(*)(int))SIGWntHandler ) == SIG_ERR )
312 std::cout << "signal error" << std::endl ;
313 CallHandler( EXCEPTION_ILLEGAL_INSTRUCTION ,0,0) ;
316 std::cout << "SIGWntHandler unexpected signal : " << signum << std::endl ;
324 //=======================================================================
325 //function : TranslateSE
326 //purpose : Translate Structural Exceptions into C++ exceptions
327 // Will be used when user's code is compiled with /EHa option
328 //=======================================================================
330 // If this file compiled with the default MSVC options for exception
331 // handling (/GX or /EHsc) then the following warning is issued:
332 // warning C4535: calling _set_se_translator() requires /EHa
333 // However it is correctly inserted and used when user's code compiled with /EHa.
334 // So, here we disable the warning.
335 #pragma warning (disable:4535)
337 static void TranslateSE( unsigned int theCode, EXCEPTION_POINTERS* theExcPtr )
339 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
340 ptrdiff_t info1 = 0, info0 = 0;
342 info1 = theExcPtr->ExceptionRecord->ExceptionInformation[1];
343 info0 = theExcPtr->ExceptionRecord->ExceptionInformation[0];
345 CallHandler(theCode, info1, info0);
349 //=======================================================================
350 //function : WntHandler
351 //purpose : Will be used when user's code is compiled with /EHs
352 // option and unless user sets his own exception handler with
353 // ::SetUnhandledExceptionFilter().
354 //=======================================================================
355 static LONG WINAPI WntHandler (EXCEPTION_POINTERS *lpXP)
357 DWORD dwExceptionCode = lpXP->ExceptionRecord->ExceptionCode;
359 return CallHandler (dwExceptionCode,
360 lpXP->ExceptionRecord->ExceptionInformation[1],
361 lpXP->ExceptionRecord->ExceptionInformation[0]);
364 //=======================================================================
365 //function : SetFloatingSignal
367 //=======================================================================
368 void OSD::SetFloatingSignal (Standard_Boolean theFloatingSignal)
373 // Note: zero bit means exception will be raised
374 _controlfp (theFloatingSignal ? 0 : _OSD_FPX, _OSD_FPX);
377 //=======================================================================
378 //function : ToCatchFloatingSignals
380 //=======================================================================
381 Standard_Boolean OSD::ToCatchFloatingSignals()
383 // return true if at least one of bits within _OSD_FPX
384 // is unset, which means relevant FPE will raise exception
385 int aControlWord = _controlfp (0, 0);
386 return (_OSD_FPX & ~aControlWord) != 0;
389 //=======================================================================
390 //function : SetThreadLocalSignal
392 //=======================================================================
393 void OSD::SetThreadLocalSignal (OSD_SignalMode theSignalMode,
394 Standard_Boolean theFloatingSignal)
397 _se_translator_function aPreviousFunc = NULL;
398 if (theSignalMode == OSD_SignalMode_Set || theSignalMode == OSD_SignalMode_SetUnhandled)
399 aPreviousFunc = _set_se_translator(TranslateSE);
400 if (theSignalMode == OSD_SignalMode_Unset || (theSignalMode == OSD_SignalMode_SetUnhandled && aPreviousFunc != NULL))
401 _set_se_translator(aPreviousFunc);
405 SetFloatingSignal (theFloatingSignal);
408 //=======================================================================
409 //function : SetSignal
411 //=======================================================================
412 void OSD::SetSignal (OSD_SignalMode theSignalMode,
413 Standard_Boolean theFloatingSignal)
415 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
416 OSD_WasSetSignal = theSignalMode;
418 #if !defined(OCCT_UWP) || defined(NTDDI_WIN10_TH2)
419 OSD_Environment env ("CSF_DEBUG_MODE");
420 TCollection_AsciiString val = env.Value();
423 std::cout << "Environment variable CSF_DEBUG_MODE setted.\n";
424 fMsgBox = Standard_True;
428 fMsgBox = Standard_False;
431 // Set exception handler (ignored when running under debugger). It will be used in most cases
432 // when user's code is compiled with /EHs
433 // Replaces the existing top-level exception filter for all existing and all future threads
434 // in the calling process
436 LPTOP_LEVEL_EXCEPTION_FILTER aPreviousFunc = NULL;
437 if (theSignalMode == OSD_SignalMode_Set || theSignalMode == OSD_SignalMode_SetUnhandled)
439 aPreviousFunc = ::SetUnhandledExceptionFilter(WntHandler);
441 if (theSignalMode == OSD_SignalMode_Unset || (theSignalMode == OSD_SignalMode_SetUnhandled && aPreviousFunc != NULL))
443 ::SetUnhandledExceptionFilter(aPreviousFunc);
446 #endif // NTDDI_WIN10_TH2
448 // Signal handlers will only be used when function ::raise() is called
450 const int aSignalTypes[NBSIG] = { SIGSEGV, SIGILL, SIGFPE };
451 for (int i = 0; i < NBSIG; ++i)
453 typedef void (*SignalFuncType)(int); // same as _crt_signal_t available since vc14
454 SignalFuncType aPreviousFunc = SIG_DFL;
455 if (theSignalMode == OSD_SignalMode_Set || theSignalMode == OSD_SignalMode_SetUnhandled)
457 aPreviousFunc = signal(aSignalTypes[i], (SignalFuncType)SIGWntHandler);
459 if (theSignalMode == OSD_SignalMode_Unset ||
460 (theSignalMode == OSD_SignalMode_SetUnhandled && aPreviousFunc != SIG_DFL && aPreviousFunc != SIG_ERR))
462 aPreviousFunc = signal(aSignalTypes[i], aPreviousFunc);
464 Standard_ASSERT(aPreviousFunc != SIG_ERR, "signal() failed", std::cout << "OSD::SetSignal(): signal() returns SIG_ERR");
467 // Set Ctrl-C and Ctrl-Break handler
468 fCtrlBrk = Standard_False;
470 if (theSignalMode == OSD_SignalMode_Set || theSignalMode == OSD_SignalMode_SetUnhandled)
472 SetConsoleCtrlHandler(&_osd_ctrl_break_handler, true);
474 else if (theSignalMode == OSD_SignalMode_Unset)
476 SetConsoleCtrlHandler(&_osd_ctrl_break_handler, false);
480 SetThreadLocalSignal (theSignalMode, theFloatingSignal);
483 //============================================================================
485 //============================================================================
486 void OSD::ControlBreak () {
488 fCtrlBrk = Standard_False;
489 throw OSD_Exception_CTRL_BREAK ( "*** INTERRUPT ***" );
491 } // end OSD :: ControlBreak
494 //============================================================================
495 //==== _osd_ctrl_break_handler
496 //============================================================================
497 static BOOL WINAPI _osd_ctrl_break_handler ( DWORD dwCode ) {
498 if ( dwCode == CTRL_C_EVENT || dwCode == CTRL_BREAK_EVENT ) {
499 MessageBeep ( MB_ICONEXCLAMATION );
500 fCtrlBrk = Standard_True;
505 } // end _osd_ctrl_break_handler
508 //============================================================================
510 //============================================================================
511 static LONG __fastcall _osd_raise ( DWORD dwCode, LPSTR msg )
513 if (msg[0] == '\x03') ++msg;
517 case EXCEPTION_ACCESS_VIOLATION:
518 THROW_OR_JUMP (OSD_Exception_ACCESS_VIOLATION, msg);
520 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
521 THROW_OR_JUMP (OSD_Exception_ARRAY_BOUNDS_EXCEEDED, msg);
523 case EXCEPTION_DATATYPE_MISALIGNMENT:
524 THROW_OR_JUMP (Standard_ProgramError, msg);
526 case EXCEPTION_ILLEGAL_INSTRUCTION:
527 THROW_OR_JUMP (OSD_Exception_ILLEGAL_INSTRUCTION, msg);
529 case EXCEPTION_IN_PAGE_ERROR:
530 THROW_OR_JUMP (OSD_Exception_IN_PAGE_ERROR, msg);
532 case EXCEPTION_INT_DIVIDE_BY_ZERO:
533 THROW_OR_JUMP (Standard_DivideByZero, msg);
535 case EXCEPTION_INT_OVERFLOW:
536 THROW_OR_JUMP (OSD_Exception_INT_OVERFLOW, msg);
538 case EXCEPTION_INVALID_DISPOSITION:
539 THROW_OR_JUMP (OSD_Exception_INVALID_DISPOSITION, msg);
541 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
542 THROW_OR_JUMP (OSD_Exception_NONCONTINUABLE_EXCEPTION, msg);
544 case EXCEPTION_PRIV_INSTRUCTION:
545 THROW_OR_JUMP (OSD_Exception_PRIV_INSTRUCTION, msg);
547 case EXCEPTION_STACK_OVERFLOW:
548 THROW_OR_JUMP (OSD_Exception_STACK_OVERFLOW, msg);
550 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
551 THROW_OR_JUMP (Standard_DivideByZero, msg);
553 case EXCEPTION_FLT_STACK_CHECK:
554 case EXCEPTION_FLT_OVERFLOW:
555 THROW_OR_JUMP (Standard_Overflow, msg);
557 case EXCEPTION_FLT_UNDERFLOW:
558 THROW_OR_JUMP (Standard_Underflow, msg);
560 case EXCEPTION_FLT_INVALID_OPERATION:
561 case EXCEPTION_FLT_DENORMAL_OPERAND:
562 case EXCEPTION_FLT_INEXACT_RESULT:
563 case STATUS_FLOAT_MULTIPLE_TRAPS:
564 case STATUS_FLOAT_MULTIPLE_FAULTS:
565 THROW_OR_JUMP (Standard_NumericError, msg);
570 return EXCEPTION_EXECUTE_HANDLER;
573 #if ! defined(OCCT_UWP) && !defined(__MINGW32__) && !defined(__CYGWIN32__)
574 //============================================================================
576 //============================================================================
577 LONG _osd_debug ( void ) {
584 HANDLE hEvent = INVALID_HANDLE_VALUE;
587 TCHAR keyValue[ MAX_PATH ];
588 TCHAR cmdLine[ MAX_PATH ];
589 SECURITY_ATTRIBUTES sa;
590 PROCESS_INFORMATION pi;
597 TEXT( "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug" ),
602 dwValueLen = sizeof ( keyValue );
604 if ( RegQueryValueEx (
605 hKey, TEXT( "Debugger" ), NULL, &dwKeyType, ( unsigned char* )keyValue, &dwValueLen
609 sa.nLength = sizeof ( SECURITY_ATTRIBUTES );
610 sa.lpSecurityDescriptor = NULL;
611 sa.bInheritHandle = TRUE;
613 if ( ( hEvent = CreateEvent ( &sa, TRUE, FALSE, NULL ) ) == NULL ) __leave;
615 StringCchPrintf(cmdLine, _countof(cmdLine), keyValue, GetCurrentProcessId(), hEvent);
617 ZeroMemory ( &si, sizeof ( STARTUPINFO ) );
619 si.cb = sizeof ( STARTUPINFO );
620 si.dwFlags = STARTF_FORCEONFEEDBACK;
622 // std::cout << "_osd_debug -> CreateProcess" << std::endl ;
623 if ( !CreateProcess (
624 NULL, cmdLine, NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE,
629 // std::cout << "_osd_debug -> WaitForSingleObject " << std::endl ;
630 WaitForSingleObject ( hEvent, INFINITE );
631 // std::cout << "_osd_debug <- WaitForSingleObject -> CloseHandle " << std::endl ;
633 CloseHandle ( pi.hProcess );
634 CloseHandle ( pi.hThread );
636 // std::cout << "_osd_debug fDbgLoaded " << std::endl ;
643 // std::cout << "_osd_debug -> CloseHandle(hKey) " << std::endl ;
644 if ( hKey != INVALID_HANDLE_VALUE ) CloseHandle ( hKey );
645 // std::cout << "_osd_debug -> CloseHandle(hEvent) " << std::endl ;
646 if ( hEvent != INVALID_HANDLE_VALUE ) CloseHandle ( hEvent );
647 // std::cout << "_osd_debug end __finally " << std::endl ;
653 action = fDbgLoaded ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER;
654 // std::cout << "_osd_debug return " << action << " EXCEPTION_CONTINUE_EXECUTION("
655 // << EXCEPTION_CONTINUE_EXECUTION << ")" << std::endl ;
659 #endif /* ! OCCT_UWP && ! __CYGWIN__ && ! __MINGW32__ */
663 //---------- All Systems except Windows NT : ----------------------------------
667 #include <OSD_WhoAmI.hxx>
668 #include <OSD_SIGHUP.hxx>
669 #include <OSD_SIGINT.hxx>
670 #include <OSD_SIGQUIT.hxx>
671 #include <OSD_SIGILL.hxx>
672 #include <OSD_SIGKILL.hxx>
673 #include <OSD_SIGBUS.hxx>
674 #include <OSD_SIGSEGV.hxx>
675 #include <OSD_SIGSYS.hxx>
676 #include <Standard_NumericError.hxx>
678 #include <Standard_ErrorHandler.hxx>
688 // variable signalling that Control-C has been pressed (SIGINT signal)
689 static Standard_Boolean fCtrlBrk;
691 //const OSD_WhoAmI Iam = OSD_WPackage;
693 typedef void (ACT_SIGIO_HANDLER)(void) ;
694 ACT_SIGIO_HANDLER *ADR_ACT_SIGIO_HANDLER = NULL ;
701 # include <sys/siginfo.h>
704 typedef void (* SIG_PFV) (int);
708 #if !defined(__ANDROID__) && !defined(__QNX__) && !defined(__EMSCRIPTEN__)
709 #include <sys/signal.h>
712 # define _OSD_FPX (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW)
714 //============================================================================
716 //==== Catche the differents signals:
717 //==== 1- The Fatal signals, which cause the end of process:
718 //==== 2- The exceptions which are "signaled" by Raise.
719 //==== The Fatal Signals:
720 //==== SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGKILL, SIGBUS, SIGSYS
721 //==== The Exceptions:
723 //==== (SUN versions)
724 //==== FPE_INTOVF_TRAP // ..... integer overflow
725 //==== FPE_INTDIV_TRAP // ..... integer divide by zero
726 //==== FPE_FLTINEX_TRAP // ..... [floating inexact result]
727 //==== FPE_FLTDIV_TRAP // ..... [floating divide by zero]
728 //==== FPE_FLTUND_TRAP // ..... [floating underflow]
729 //==== FPE_FLTOPER_TRAP // ..... [floating inexact result]
730 //==== FPE_FLTOVF_TRAP // ..... [floating overflow]
731 //==== SIGSEGV is handled by "SegvHandler()"
732 //============================================================================
734 static void Handler (const int theSignal, siginfo_t */*theSigInfo*/, const Standard_Address /*theContext*/)
736 static void Handler (const int theSignal)
739 struct sigaction oldact, act;
740 // re-install the signal
741 if ( ! sigaction (theSignal, NULL, &oldact) ) {
742 // std::cout << " signal is " << theSignal << " handler is " << oldact.sa_handler << std::endl;
743 if (sigaction (theSignal, &oldact, &act)) perror ("sigaction");
746 perror ("sigaction");
749 // std::cout << "OSD::Handler: signal " << (int) theSignal << " occured inside a try block " << std::endl ;
750 if ( ADR_ACT_SIGIO_HANDLER != NULL )
751 (*ADR_ACT_SIGIO_HANDLER)() ;
757 OSD_SIGHUP::NewInstance("SIGHUP 'hangup' detected.")->Jump();
761 // For safe handling of Control-C as stop event, arm a variable but do not
762 // generate longjump (we are out of context anyway)
763 fCtrlBrk = Standard_True;
764 // OSD_SIGINT::NewInstance("SIGINT 'interrupt' detected.")->Jump();
768 OSD_SIGQUIT::NewInstance("SIGQUIT 'quit' detected.")->Jump();
772 OSD_SIGILL::NewInstance("SIGILL 'illegal instruction' detected.")->Jump();
776 OSD_SIGKILL::NewInstance("SIGKILL 'kill' detected.")->Jump();
780 sigaddset(&set, SIGBUS);
781 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
782 OSD_SIGBUS::NewInstance("SIGBUS 'bus error' detected.")->Jump();
786 OSD_SIGSEGV::NewInstance("SIGSEGV 'segmentation violation' detected.")->Jump();
791 OSD_SIGSYS::NewInstance("SIGSYS 'bad argument to system call' detected.")->Jump();
796 sigaddset(&set, SIGFPE);
797 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
799 OSD::SetFloatingSignal (Standard_True);
801 #if (!defined (__sun)) && (!defined(SOLARIS))
802 Standard_NumericError::NewInstance("SIGFPE Arithmetic exception detected")->Jump();
807 switch(aSigInfo->si_code) {
808 case FPE_FLTDIV_TRAP :
809 Standard_DivideByZero::NewInstance("Floating Divide By Zero")->Jump();
811 case FPE_INTDIV_TRAP :
812 Standard_DivideByZero::NewInstance("Integer Divide By Zero")->Jump();
814 case FPE_FLTOVF_TRAP :
815 Standard_Overflow::NewInstance("Floating Overflow")->Jump();
817 case FPE_INTOVF_TRAP :
818 Standard_Overflow::NewInstance("Integer Overflow")->Jump();
820 case FPE_FLTUND_TRAP :
821 Standard_NumericError::NewInstance("Floating Underflow")->Jump();
823 case FPE_FLTRES_TRAP:
824 Standard_NumericError::NewInstance("Floating Point Inexact Result")->Jump();
826 case FPE_FLTINV_TRAP :
827 Standard_NumericError::NewInstance("Invalid Floating Point Operation")->Jump();
830 Standard_NumericError::NewInstance("Numeric Error")->Jump();
834 Standard_NumericError::NewInstance("SIGFPE Arithmetic exception detected")->Jump();
840 std::cout << "Unexpected signal " << theSignal << std::endl ;
846 //============================================================================
848 //============================================================================
851 static void SegvHandler(const int theSignal,
853 const Standard_Address theContext)
855 (void)theSignal; // silence GCC warnings
858 // std::cout << "OSD::SegvHandler activated(SA_SIGINFO)" << std::endl ;
862 sigaddset(&set, SIGSEGV);
863 sigprocmask (SIG_UNBLOCK, &set, NULL) ;
864 void *address = ip->si_addr ;
867 sprintf(Msg,"SIGSEGV 'segmentation violation' detected. Address %lx",
869 OSD_SIGSEGV::NewInstance(Msg)->Jump();
874 std::cout << "Wrong undefined address." << std::endl ;
880 #elif defined (_hpux) || defined(HPUX)
881 // Not ACTIVE ? SA_SIGINFO is defined on SUN, OSF, SGI and HP (and Linux) !
882 // pour version 09.07
884 static void SegvHandler(const int theSignal,
886 const Standard_Address theContext)
888 unsigned long Space ;
889 unsigned long Offset ;
892 if ( theContext != NULL ) {
893 Space = ((struct sigcontext *)theContext)->sc_sl.sl_ss.ss_cr20 ;
894 Offset = ((struct sigcontext *)theContext)->sc_sl.sl_ss.ss_cr21 ;
895 // std::cout << "Wrong address = " << hex(Offset) << std::endl ;
897 sprintf(Msg,"SIGSEGV 'segmentation violation' detected. Address %lx",Offset) ;
898 OSD_SIGSEGV::Jump(Msg);
899 // scp->sc_pcoq_head = scp->sc_pcoq_tail ; Permettrait de continuer a
900 // scp->sc_pcoq_tail = scp->sc_pcoq_tail + 0x4 ; l'intruction suivant le segv.
905 std::cout << "Wrong undefined address." << std::endl ;
913 //=======================================================================
914 //function : SetFloatingSignal
916 //=======================================================================
917 void OSD::SetFloatingSignal (Standard_Boolean theFloatingSignal)
919 #if defined (__linux__)
920 feclearexcept (FE_ALL_EXCEPT);
921 if (theFloatingSignal)
923 feenableexcept (_OSD_FPX);
927 fedisableexcept (_OSD_FPX);
929 #elif defined (__sun) || defined (SOLARIS)
931 sigfpe_handler_type anFpeHandler = (theFloatingSignal ? (sigfpe_handler_type)Handler : NULL);
932 aSunStat = ieee_handler ("set", "invalid", anFpeHandler);
933 aSunStat = ieee_handler ("set", "division", anFpeHandler) || aSunStat;
934 aSunStat = ieee_handler ("set", "overflow", anFpeHandler) || aSunStat;
938 std::cerr << "ieee_handler does not work !!! KO\n";
942 (void)theFloatingSignal;
946 //=======================================================================
947 //function : ToCatchFloatingSignals
949 //=======================================================================
950 Standard_Boolean OSD::ToCatchFloatingSignals()
952 #if defined (__linux__)
953 return (fegetexcept() & _OSD_FPX) != 0;
955 return Standard_False;
959 //=======================================================================
960 //function : SetThreadLocalSignal
962 //=======================================================================
963 void OSD::SetThreadLocalSignal (OSD_SignalMode /*theSignalMode*/,
964 Standard_Boolean theFloatingSignal)
966 SetFloatingSignal (theFloatingSignal);
969 //============================================================================
971 //==== Set the differents signals:
972 //============================================================================
974 void OSD::SetSignal (OSD_SignalMode theSignalMode,
975 Standard_Boolean theFloatingSignal)
977 SetFloatingSignal (theFloatingSignal);
979 OSD_WasSetSignal = theSignalMode;
980 if (theSignalMode == OSD_SignalMode_AsIs)
982 return; // nothing to be done with signal handlers
985 // Prepare signal descriptors
986 struct sigaction anActSet, anActDfl, anActOld;
987 sigemptyset(&anActSet.sa_mask);
988 sigemptyset(&anActDfl.sa_mask);
989 sigemptyset(&anActOld.sa_mask);
991 anActSet.sa_flags = anActDfl.sa_flags = anActOld.sa_flags = SA_RESTART;
993 anActSet.sa_flags = anActDfl.sa_flags = anActOld.sa_flags = 0;
996 anActSet.sa_flags = anActSet.sa_flags | SA_SIGINFO;
997 anActSet.sa_sigaction = Handler;
999 anActSet.sa_handler = Handler;
1001 anActDfl.sa_handler = SIG_DFL;
1003 // Set signal handlers; NB: SIGSEGV must be the last one!
1004 const int NBSIG = 8;
1005 const int aSignalTypes[NBSIG] = { SIGFPE, SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGBUS, SIGSYS, SIGSEGV };
1006 for (int i = 0; i < NBSIG; ++i)
1008 // SIGSEGV has special handler
1009 if (aSignalTypes[i] == SIGSEGV)
1012 anActSet.sa_sigaction = /*(void(*)(int, siginfo_t *, void*))*/ SegvHandler;
1014 anActSet.sa_handler = /*(SIG_PFV)*/ SegvHandler;
1018 // set handler according to specified mode and current handler
1020 if (theSignalMode == OSD_SignalMode_Set || theSignalMode == OSD_SignalMode_SetUnhandled)
1022 retcode = sigaction (aSignalTypes[i], &anActSet, &anActOld);
1024 else if (theSignalMode == OSD_SignalMode_Unset)
1026 retcode = sigaction (aSignalTypes[i], &anActDfl, &anActOld);
1028 if (theSignalMode == OSD_SignalMode_SetUnhandled && retcode == 0 && anActOld.sa_handler != SIG_DFL)
1030 struct sigaction anActOld2;
1031 sigemptyset(&anActOld2.sa_mask);
1032 retcode = sigaction (aSignalTypes[i], &anActOld, &anActOld2);
1034 Standard_ASSERT(retcode == 0, "sigaction() failed", std::cout << "OSD::SetSignal(): sigaction() failed for " << aSignalTypes[i] << std::endl);
1038 //============================================================================
1040 //============================================================================
1042 void OSD :: ControlBreak ()
1045 fCtrlBrk = Standard_False;
1046 throw OSD_Exception_CTRL_BREAK ("*** INTERRUPT ***");