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>
21 //---------------------------- Windows NT System --------------------------------
34 #ifndef STATUS_FLOAT_MULTIPLE_FAULTS
36 #define STATUS_FLOAT_MULTIPLE_FAULTS (0xC00002B4L)
37 #define STATUS_FLOAT_MULTIPLE_TRAPS (0xC00002B5L)
40 #include <OSD_Exception_ACCESS_VIOLATION.hxx>
41 #include <OSD_Exception_ARRAY_BOUNDS_EXCEEDED.hxx>
42 #include <OSD_Exception_ILLEGAL_INSTRUCTION.hxx>
43 #include <OSD_Exception_IN_PAGE_ERROR.hxx>
44 #include <OSD_Exception_INT_DIVIDE_BY_ZERO.hxx>
45 #include <OSD_Exception_INT_OVERFLOW.hxx>
46 #include <OSD_Exception_INVALID_DISPOSITION.hxx>
47 #include <OSD_Exception_NONCONTINUABLE_EXCEPTION.hxx>
48 #include <OSD_Exception_PRIV_INSTRUCTION.hxx>
49 #include <OSD_Exception_STACK_OVERFLOW.hxx>
50 #include <OSD_Exception_STATUS_NO_MEMORY.hxx>
52 #include <OSD_Environment.hxx>
53 #include <Standard_Underflow.hxx>
54 #include <Standard_ProgramError.hxx>
55 #include <Standard_Mutex.hxx>
57 #include <OSD_WNT_1.hxx>
68 static Standard_Boolean fCtrlBrk;
69 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
70 static Standard_Boolean fMsgBox;
71 static Standard_Boolean fFltExceptions;
72 static Standard_Boolean fDbgLoaded;
74 // used to forbid simultaneous execution of setting / executing handlers
75 static Standard_Mutex THE_SIGNAL_MUTEX;
77 static LONG __fastcall _osd_raise ( DWORD, LPSTR );
78 static BOOL WINAPI _osd_ctrl_break_handler ( DWORD );
81 static LONG _osd_debug ( void );
84 //# define _OSD_FPX ( _EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW )
85 # define _OSD_FPX ( _EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW )
87 //=======================================================================
88 //function : CallHandler
90 //=======================================================================
91 static LONG CallHandler (DWORD dwExceptionCode,
92 ptrdiff_t ExceptionInformation1,
93 ptrdiff_t ExceptionInformation0)
95 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
97 static wchar_t buffer[2048];
103 // cout << "CallHandler " << dwExceptionCode << endl ;
104 switch ( dwExceptionCode ) {
105 case EXCEPTION_FLT_DENORMAL_OPERAND:
106 // cout << "CallHandler : EXCEPTION_FLT_DENORMAL_OPERAND:" << endl ;
107 StringCchCopyW (buffer, _countof(buffer), L"FLT DENORMAL OPERAND");
110 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
111 // cout << "CallHandler : EXCEPTION_FLT_DIVIDE_BY_ZERO:" << endl ;
112 StringCchCopyW (buffer, _countof(buffer), L"FLT DIVIDE BY ZERO");
115 case EXCEPTION_FLT_INEXACT_RESULT:
116 // cout << "CallHandler : EXCEPTION_FLT_INEXACT_RESULT:" << endl ;
117 StringCchCopyW (buffer, _countof(buffer), L"FLT INEXACT RESULT");
120 case EXCEPTION_FLT_INVALID_OPERATION:
121 // cout << "CallHandler : EXCEPTION_FLT_INVALID_OPERATION:" << endl ;
122 StringCchCopyW (buffer, _countof(buffer), L"FLT INVALID OPERATION");
125 case EXCEPTION_FLT_OVERFLOW:
126 // cout << "CallHandler : EXCEPTION_FLT_OVERFLOW:" << endl ;
127 StringCchCopyW (buffer, _countof(buffer), L"FLT OVERFLOW");
130 case EXCEPTION_FLT_STACK_CHECK:
131 // cout << "CallHandler : EXCEPTION_FLT_STACK_CHECK:" << endl ;
132 StringCchCopyW (buffer, _countof(buffer), L"FLT STACK CHECK");
135 case EXCEPTION_FLT_UNDERFLOW:
136 // cout << "CallHandler : EXCEPTION_FLT_UNDERFLOW:" << endl ;
137 StringCchCopyW (buffer, _countof(buffer), L"FLT UNDERFLOW");
140 case STATUS_FLOAT_MULTIPLE_TRAPS:
141 // cout << "CallHandler : EXCEPTION_FLT_UNDERFLOW:" << endl ;
142 StringCchCopyW (buffer, _countof(buffer), L"FLT MULTIPLE TRAPS (possible overflow in conversion of double to integer)");
145 case STATUS_FLOAT_MULTIPLE_FAULTS:
146 // cout << "CallHandler : EXCEPTION_FLT_UNDERFLOW:" << endl ;
147 StringCchCopyW (buffer, _countof(buffer), L"FLT MULTIPLE FAULTS");
150 case STATUS_NO_MEMORY:
151 // cout << "CallHandler : STATUS_NO_MEMORY:" << endl ;
152 OSD_Exception_STATUS_NO_MEMORY ::
153 Raise ( "MEMORY ALLOCATION ERROR ( no room in the process heap )" );
154 case EXCEPTION_ACCESS_VIOLATION:
155 // cout << "CallHandler : EXCEPTION_ACCESS_VIOLATION:" << endl ;
156 StringCchPrintfW (buffer, _countof(buffer), L"%s%s%s0x%.8p%s%s%s", L"ACCESS VIOLATION",
157 fMsgBox ? L"\n" : L" ", L"at address ",
158 ExceptionInformation1 ,
160 ExceptionInformation0 ? L"WRITE" : L"READ",
163 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
164 // cout << "CallHandler : EXCEPTION_ARRAY_BOUNDS_EXCEEDED:" << endl ;
165 StringCchCopyW (buffer, _countof(buffer), L"ARRAY BOUNDS EXCEEDED");
167 case EXCEPTION_DATATYPE_MISALIGNMENT:
168 // cout << "CallHandler : EXCEPTION_DATATYPE_MISALIGNMENT:" << endl ;
169 StringCchCopyW (buffer, _countof(buffer), L"DATATYPE MISALIGNMENT");
172 case EXCEPTION_ILLEGAL_INSTRUCTION:
173 // cout << "CallHandler : EXCEPTION_ILLEGAL_INSTRUCTION:" << endl ;
174 StringCchCopyW (buffer, _countof(buffer), L"ILLEGAL INSTRUCTION");
177 case EXCEPTION_IN_PAGE_ERROR:
178 // cout << "CallHandler : EXCEPTION_IN_PAGE_ERROR:" << endl ;
179 StringCchCopyW (buffer, _countof(buffer), L"IN_PAGE ERROR");
182 case EXCEPTION_INT_DIVIDE_BY_ZERO:
183 // cout << "CallHandler : EXCEPTION_INT_DIVIDE_BY_ZERO:" << endl ;
184 StringCchCopyW (buffer, _countof(buffer), L"INTEGER DIVISION BY ZERO");
187 case EXCEPTION_INT_OVERFLOW:
188 // cout << "CallHandler : EXCEPTION_INT_OVERFLOW:" << endl ;
189 StringCchCopyW (buffer, _countof(buffer), L"INTEGER OVERFLOW");
192 case EXCEPTION_INVALID_DISPOSITION:
193 // cout << "CallHandler : EXCEPTION_INVALID_DISPOSITION:" << endl ;
194 StringCchCopyW (buffer, _countof(buffer), L"INVALID DISPOSITION");
197 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
198 // cout << "CallHandler : EXCEPTION_NONCONTINUABLE_EXCEPTION:" << endl ;
199 StringCchCopyW (buffer, _countof(buffer), L"NONCONTINUABLE EXCEPTION");
202 case EXCEPTION_PRIV_INSTRUCTION:
203 // cout << "CallHandler : EXCEPTION_PRIV_INSTRUCTION:" << endl ;
204 StringCchCopyW (buffer, _countof(buffer), L"PRIVELEGED INSTRUCTION ENCOUNTERED");
207 case EXCEPTION_STACK_OVERFLOW:
208 // cout << "CallHandler : EXCEPTION_STACK_OVERFLOW:" << endl ;
209 #if defined( _MSC_VER ) && ( _MSC_VER >= 1300 ) && !defined(OCCT_UWP)
210 // try recovering from stack overflow: available in MS VC++ 7.0
211 if (!_resetstkoflw())
212 StringCchCopyW (buffer, _countof(buffer), L"Unrecoverable STACK OVERFLOW");
215 StringCchCopyW (buffer, _countof(buffer), L"STACK OVERFLOW");
219 StringCchPrintfW (buffer, _countof(buffer), L"unknown exception code 0x%x, params 0x%p 0x%p",
220 dwExceptionCode, ExceptionInformation1, ExceptionInformation0 );
224 // provide message to the user with possibility to stop
226 StringCchLengthW (buffer, _countof(buffer),&idx);
227 if ( idx && fMsgBox && dwExceptionCode != EXCEPTION_NONCONTINUABLE_EXCEPTION ) {
228 // reset FP operations before message box, otherwise it may fail to show up
233 MessageBeep ( MB_ICONHAND );
234 int aChoice = ::MessageBoxW (0, buffer, L"OCCT Exception Handler", MB_ABORTRETRYIGNORE | MB_ICONSTOP);
235 if (aChoice == IDRETRY)
239 } else if (aChoice == IDABORT)
246 if ( !fFltExceptions ) return EXCEPTION_EXECUTE_HANDLER;
249 _controlfp ( 0, _OSD_FPX ) ; // JR add :
250 // cout << "OSD::WntHandler _controlfp( 0, _OSD_FPX ) " << hex << _controlfp(0,0) << dec << endl ;
254 WideCharToMultiByte(CP_UTF8, 0, buffer, -1, aBufferA, sizeof(aBufferA), NULL, NULL);
255 return _osd_raise(dwExceptionCode, aBufferA);
258 //=======================================================================
259 //function : SIGWntHandler
260 //purpose : Will only be used if user calls ::raise() function with
261 // signal type set in OSD::SetSignal() - SIGSEGV, SIGFPE, SIGILL
262 // (the latter will likely be removed in the future)
263 //=======================================================================
264 static void SIGWntHandler (int signum, int sub_code)
266 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
269 if ( signal( signum , (void(*)(int))SIGWntHandler ) == SIG_ERR )
270 cout << "signal error" << endl ;
273 CallHandler( EXCEPTION_FLT_INVALID_OPERATION ,0,0) ;
276 CallHandler( EXCEPTION_FLT_DENORMAL_OPERAND ,0,0) ;
278 case _FPE_ZERODIVIDE :
279 CallHandler( EXCEPTION_FLT_DIVIDE_BY_ZERO ,0,0) ;
282 CallHandler( EXCEPTION_FLT_OVERFLOW ,0,0) ;
284 case _FPE_UNDERFLOW :
285 CallHandler( EXCEPTION_FLT_UNDERFLOW ,0,0) ;
288 CallHandler( EXCEPTION_FLT_INEXACT_RESULT ,0,0) ;
291 cout << "SIGWntHandler(default) -> Standard_NumericError::Raise(\"Floating Point Error\");" << endl;
292 Standard_NumericError::Raise("Floating Point Error");
297 if ( signal( signum, (void(*)(int))SIGWntHandler ) == SIG_ERR )
298 cout << "signal error" << endl ;
299 CallHandler( EXCEPTION_ACCESS_VIOLATION ,0,0) ;
302 if ( signal( signum, (void(*)(int))SIGWntHandler ) == SIG_ERR )
303 cout << "signal error" << endl ;
304 CallHandler( EXCEPTION_ILLEGAL_INSTRUCTION ,0,0) ;
307 cout << "SIGWntHandler unexpected signal : " << signum << endl ;
316 //=======================================================================
317 //function : TranslateSE
318 //purpose : Translate Structural Exceptions into C++ exceptions
319 // Will be used when user's code is compiled with /EHa option
320 //=======================================================================
322 // If this file compiled with the default MSVC options for exception
323 // handling (/GX or /EHsc) then the following warning is issued:
324 // warning C4535: calling _set_se_translator() requires /EHa
325 // However it is correctly inserted and used when user's code compiled with /EHa.
326 // So, here we disable the warning.
327 #pragma warning (disable:4535)
329 static void TranslateSE( unsigned int theCode, EXCEPTION_POINTERS* theExcPtr )
331 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
332 ptrdiff_t info1 = 0, info0 = 0;
334 info1 = theExcPtr->ExceptionRecord->ExceptionInformation[1];
335 info0 = theExcPtr->ExceptionRecord->ExceptionInformation[0];
337 CallHandler(theCode, info1, info0);
341 //=======================================================================
342 //function : WntHandler
343 //purpose : Will be used when user's code is compiled with /EHs
344 // option and unless user sets his own exception handler with
345 // ::SetUnhandledExceptionFilter().
346 //=======================================================================
347 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
348 static LONG WINAPI WntHandler (EXCEPTION_POINTERS *lpXP)
350 DWORD dwExceptionCode = lpXP->ExceptionRecord->ExceptionCode;
352 return CallHandler (dwExceptionCode,
353 lpXP->ExceptionRecord->ExceptionInformation[1],
354 lpXP->ExceptionRecord->ExceptionInformation[0]);
358 //=======================================================================
359 //function : SetSignal
361 //=======================================================================
362 void OSD::SetSignal (const Standard_Boolean theFloatingSignal)
364 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
365 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
366 #if !defined(OCCT_UWP) || defined(NTDDI_WIN10_TH2)
367 LPTOP_LEVEL_EXCEPTION_FILTER aPreviousFilter;
369 OSD_Environment env ("CSF_DEBUG_MODE");
370 TCollection_AsciiString val = env.Value();
373 cout << "Environment variable CSF_DEBUG_MODE setted.\n";
374 fMsgBox = Standard_True;
378 fMsgBox = Standard_False;
381 // Set exception handler (ignored when running under debugger). It will be used in most cases
382 // when user's code is compiled with /EHs
383 // Replaces the existing top-level exception filter for all existing and all future threads
384 // in the calling process
385 aPreviousFilter = ::SetUnhandledExceptionFilter (/*(LPTOP_LEVEL_EXCEPTION_FILTER)*/ WntHandler);
386 #endif // NTDDI_WIN10_TH2
388 // Signal handlers will only be used when the method ::raise() will be used
389 // Handlers must be set for every thread
390 if (signal (SIGSEGV, (void(*)(int))SIGWntHandler) == SIG_ERR)
391 cout << "signal(OSD::SetSignal) error\n";
392 if (signal (SIGFPE, (void(*)(int))SIGWntHandler) == SIG_ERR)
393 cout << "signal(OSD::SetSignal) error\n";
394 if (signal (SIGILL, (void(*)(int))SIGWntHandler) == SIG_ERR)
395 cout << "signal(OSD::SetSignal) error\n";
397 // Set Ctrl-C and Ctrl-Break handler
398 fCtrlBrk = Standard_False;
400 SetConsoleCtrlHandler (&_osd_ctrl_break_handler, TRUE);
403 // _se_translator_function pOldSeFunc =
404 _set_se_translator (TranslateSE);
407 fFltExceptions = theFloatingSignal;
408 if (theFloatingSignal)
410 _controlfp (0, _OSD_FPX); // JR add :
413 _controlfp (_OSD_FPX, _OSD_FPX); // JR add :
416 } // end OSD :: SetSignal
418 //============================================================================
420 //============================================================================
421 void OSD::ControlBreak () {
423 fCtrlBrk = Standard_False;
424 OSD_Exception_CTRL_BREAK :: Raise ( "*** INTERRUPT ***" );
426 } // end OSD :: ControlBreak
427 #if !defined(__MINGW32__) && !defined(__CYGWIN32__)
429 //============================================================================
430 //==== _osd_ctrl_break_handler
431 //============================================================================
432 static BOOL WINAPI _osd_ctrl_break_handler ( DWORD dwCode ) {
433 if ( dwCode == CTRL_C_EVENT || dwCode == CTRL_BREAK_EVENT ) {
434 MessageBeep ( MB_ICONEXCLAMATION );
435 fCtrlBrk = Standard_True;
440 } // end _osd_ctrl_break_handler
442 //============================================================================
444 //============================================================================
445 static LONG __fastcall _osd_raise ( DWORD dwCode, LPSTR msg )
447 if (msg[0] == '\x03') ++msg;
451 case EXCEPTION_ACCESS_VIOLATION:
452 OSD_Exception_ACCESS_VIOLATION::Raise (msg);
454 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
455 OSD_Exception_ARRAY_BOUNDS_EXCEEDED::Raise (msg);
457 case EXCEPTION_DATATYPE_MISALIGNMENT:
458 Standard_ProgramError::Raise (msg);
460 case EXCEPTION_ILLEGAL_INSTRUCTION:
461 OSD_Exception_ILLEGAL_INSTRUCTION::Raise (msg);
463 case EXCEPTION_IN_PAGE_ERROR:
464 OSD_Exception_IN_PAGE_ERROR::Raise (msg);
466 case EXCEPTION_INT_DIVIDE_BY_ZERO:
467 Standard_DivideByZero::Raise (msg);
469 case EXCEPTION_INT_OVERFLOW:
470 OSD_Exception_INT_OVERFLOW::Raise (msg);
472 case EXCEPTION_INVALID_DISPOSITION:
473 OSD_Exception_INVALID_DISPOSITION::Raise (msg);
475 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
476 OSD_Exception_NONCONTINUABLE_EXCEPTION::Raise (msg);
478 case EXCEPTION_PRIV_INSTRUCTION:
479 OSD_Exception_PRIV_INSTRUCTION::Raise (msg);
481 case EXCEPTION_STACK_OVERFLOW:
482 OSD_Exception_STACK_OVERFLOW::Raise (msg);
484 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
485 Standard_DivideByZero::Raise (msg);
487 case EXCEPTION_FLT_STACK_CHECK:
488 case EXCEPTION_FLT_OVERFLOW:
489 Standard_Overflow::Raise (msg);
491 case EXCEPTION_FLT_UNDERFLOW:
492 Standard_Underflow::Raise (msg);
494 case EXCEPTION_FLT_INVALID_OPERATION:
495 case EXCEPTION_FLT_DENORMAL_OPERAND:
496 case EXCEPTION_FLT_INEXACT_RESULT:
497 case STATUS_FLOAT_MULTIPLE_TRAPS:
498 case STATUS_FLOAT_MULTIPLE_FAULTS:
499 Standard_NumericError::Raise (msg);
504 return EXCEPTION_EXECUTE_HANDLER;
507 //============================================================================
509 //============================================================================
511 LONG _osd_debug ( void ) {
518 HANDLE hEvent = INVALID_HANDLE_VALUE;
521 TCHAR keyValue[ MAX_PATH ];
522 TCHAR cmdLine[ MAX_PATH ];
523 SECURITY_ATTRIBUTES sa;
524 PROCESS_INFORMATION pi;
531 TEXT( "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug" ),
536 dwValueLen = sizeof ( keyValue );
538 if ( RegQueryValueEx (
539 hKey, TEXT( "Debugger" ), NULL, &dwKeyType, ( unsigned char* )keyValue, &dwValueLen
543 sa.nLength = sizeof ( SECURITY_ATTRIBUTES );
544 sa.lpSecurityDescriptor = NULL;
545 sa.bInheritHandle = TRUE;
547 if ( ( hEvent = CreateEvent ( &sa, TRUE, FALSE, NULL ) ) == NULL ) __leave;
549 StringCchPrintf(cmdLine, _countof(cmdLine), keyValue, GetCurrentProcessId(), hEvent);
551 ZeroMemory ( &si, sizeof ( STARTUPINFO ) );
553 si.cb = sizeof ( STARTUPINFO );
554 si.dwFlags = STARTF_FORCEONFEEDBACK;
556 // cout << "_osd_debug -> CreateProcess" << endl ;
557 if ( !CreateProcess (
558 NULL, cmdLine, NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE,
563 // cout << "_osd_debug -> WaitForSingleObject " << endl ;
564 WaitForSingleObject ( hEvent, INFINITE );
565 // cout << "_osd_debug <- WaitForSingleObject -> CloseHandle " << endl ;
567 CloseHandle ( pi.hProcess );
568 CloseHandle ( pi.hThread );
570 // cout << "_osd_debug fDbgLoaded " << endl ;
577 // cout << "_osd_debug -> CloseHandle(hKey) " << endl ;
578 if ( hKey != INVALID_HANDLE_VALUE ) CloseHandle ( hKey );
579 // cout << "_osd_debug -> CloseHandle(hEvent) " << endl ;
580 if ( hEvent != INVALID_HANDLE_VALUE ) CloseHandle ( hEvent );
581 // cout << "_osd_debug end __finally " << endl ;
587 action = fDbgLoaded ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER;
588 // cout << "_osd_debug return " << action << " EXCEPTION_CONTINUE_EXECUTION("
589 // << EXCEPTION_CONTINUE_EXECUTION << ")" << endl ;
598 //---------- All Systems except Windows NT : ----------------------------------
602 #include <OSD_WhoAmI.hxx>
603 #include <OSD_SIGHUP.hxx>
604 #include <OSD_SIGINT.hxx>
605 #include <OSD_SIGQUIT.hxx>
606 #include <OSD_SIGILL.hxx>
607 #include <OSD_SIGKILL.hxx>
608 #include <OSD_SIGBUS.hxx>
609 #include <OSD_SIGSEGV.hxx>
610 #include <OSD_SIGSYS.hxx>
611 #include <Standard_NumericError.hxx>
613 #include <Standard_ErrorHandler.hxx>
620 static Standard_Boolean fFltExceptions = Standard_False;
623 // variable signalling that Control-C has been pressed (SIGINT signal)
624 static Standard_Boolean fCtrlBrk;
626 //const OSD_WhoAmI Iam = OSD_WPackage;
628 typedef void (ACT_SIGIO_HANDLER)(void) ;
629 ACT_SIGIO_HANDLER *ADR_ACT_SIGIO_HANDLER = NULL ;
632 typedef void (* SIG_PFV) (int);
641 # include <sys/siginfo.h>
645 typedef void (* SIG_PFV) (int);
649 #if !defined(__ANDROID__) && !defined(__QNX__)
650 #include <sys/signal.h>
653 #if defined(HAVE_PTHREAD_H) && defined(NO_CXX_EXCEPTION)
654 //============================================================================
655 //==== GetOldSigAction
657 //============================================================================
659 static struct sigaction *GetOldSigAction()
661 static struct sigaction oldSignals[NSIG];
666 static sigfpe_handler_type *GetOldFPE()
668 static sigfpe_handler_type aIEEEHandler[5] = { NULL, NULL, NULL, NULL, NULL } ;
674 //============================================================================
676 //==== Catche the differents signals:
677 //==== 1- The Fatal signals, which cause the end of process:
678 //==== 2- The exceptions which are "signaled" by Raise.
679 //==== The Fatal Signals:
680 //==== SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGKILL, SIGBUS, SIGSYS
681 //==== The Exceptions:
683 //==== (SUN versions)
684 //==== FPE_INTOVF_TRAP // ..... integer overflow
685 //==== FPE_INTDIV_TRAP // ..... integer divide by zero
686 //==== FPE_FLTINEX_TRAP // ..... [floating inexact result]
687 //==== FPE_FLTDIV_TRAP // ..... [floating divide by zero]
688 //==== FPE_FLTUND_TRAP // ..... [floating underflow]
689 //==== FPE_FLTOPER_TRAP // ..... [floating inexact result]
690 //==== FPE_FLTOVF_TRAP // ..... [floating overflow]
691 //==== SIGSEGV is handled by "SegvHandler()"
692 //============================================================================
694 #if defined(HAVE_PTHREAD_H) && defined(NO_CXX_EXCEPTION)
695 static void Handler (const int theSignal, siginfo_t *theSigInfo, const Standard_Address theContext)
697 static void Handler (const int theSignal, siginfo_t */*theSigInfo*/, const Standard_Address /*theContext*/)
700 static void Handler (const int theSignal)
703 struct sigaction oldact, act;
704 // re-install the signal
705 if ( ! sigaction (theSignal, NULL, &oldact) ) {
706 // cout << " signal is " << theSignal << " handler is " << oldact.sa_handler << endl;
707 if (sigaction (theSignal, &oldact, &act)) perror ("sigaction");
710 perror ("sigaction");
713 #if defined(HAVE_PTHREAD_H) && defined(NO_CXX_EXCEPTION)
714 if (pthread_self() != getOCCThread() || !Standard_ErrorHandler::IsInTryBlock()) {
715 // use the previous signal handler
716 // cout << "OSD::Handler: signal " << (int) theSignal << " occured outside a try block " << endl ;
717 struct sigaction *oldSignals = GetOldSigAction();
718 struct sigaction asigacthandler = oldSignals[theSignal >= 0 && theSignal < NSIG ? theSignal : 0];
720 if (asigacthandler.sa_flags & SA_SIGINFO) {
721 void (*aCurInfoHandle)(int, siginfo_t *, void *) = asigacthandler.sa_sigaction;
723 siginfo_t * aSigInfo = NULL;
725 aSigInfo = theSigInfo;
729 switch (aSigInfo->si_signo) {
733 sigfpe_handler_type *aIEEEHandlerTab = GetOldFPE();
734 sigfpe_handler_type aIEEEHandler = NULL;
735 switch (aSigInfo->si_code) {
736 case FPE_INTDIV_TRAP :
737 case FPE_FLTDIV_TRAP :
738 aIEEEHandler = aIEEEHandlerTab[1];
740 case FPE_INTOVF_TRAP :
741 case FPE_FLTOVF_TRAP :
742 aIEEEHandler = aIEEEHandlerTab[2];
744 case FPE_FLTUND_TRAP :
745 aIEEEHandler = aIEEEHandlerTab[4];
747 case FPE_FLTRES_TRAP :
748 aIEEEHandler = aIEEEHandlerTab[3];
750 case FPE_FLTINV_TRAP :
751 aIEEEHandler = aIEEEHandlerTab[0];
753 case FPE_FLTSUB_TRAP :
758 // cout << "OSD::Handler: calling previous IEEE signal handler with info" << endl ;
759 (*aIEEEHandler) (theSignal, aSigInfo, theContext);
769 if (aCurInfoHandle) {
770 // cout << "OSD::Handler: calling previous signal handler with info " << aCurInfoHandle << endl ;
771 (*aCurInfoHandle) (theSignal, aSigInfo, theContext);
773 cerr << " previous signal handler return" << endl ;
778 // cout << "OSD::Handler: no handler with info for the signal" << endl;
782 // no siginfo needed for the signal
783 void (*aCurHandler) (int) = asigacthandler.sa_handler;
785 // cout << "OSD::Handler: calling previous signal handler" << endl ;
786 (*aCurHandler) (theSignal);
788 cerr << " previous signal handler return" << endl ;
793 // cout << " Signal occured outside a try block, but no handler for it" <<endl;
798 // cout << "OSD::Handler: signal " << (int) theSignal << " occured inside a try block " << endl ;
799 if ( ADR_ACT_SIGIO_HANDLER != NULL )
800 (*ADR_ACT_SIGIO_HANDLER)() ;
803 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
804 //feenableexcept (FE_INVALID | FE_DIVBYZERO);
810 OSD_SIGHUP::NewInstance("SIGHUP 'hangup' detected.")->Jump();
814 // For safe handling of Control-C as stop event, arm a variable but do not
815 // generate longjump (we are out of context anyway)
816 fCtrlBrk = Standard_True;
817 // OSD_SIGINT::NewInstance("SIGINT 'interrupt' detected.")->Jump();
821 OSD_SIGQUIT::NewInstance("SIGQUIT 'quit' detected.")->Jump();
825 OSD_SIGILL::NewInstance("SIGILL 'illegal instruction' detected.")->Jump();
829 OSD_SIGKILL::NewInstance("SIGKILL 'kill' detected.")->Jump();
833 sigaddset(&set, SIGBUS);
834 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
835 OSD_SIGBUS::NewInstance("SIGBUS 'bus error' detected.")->Jump();
839 OSD_SIGSEGV::NewInstance("SIGSEGV 'segmentation violation' detected.")->Jump();
844 OSD_SIGSYS::NewInstance("SIGSYS 'bad argument to system call' detected.")->Jump();
849 sigaddset(&set, SIGFPE);
850 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
852 // Pour DEC/OSF1 SIGFPE = Division par zero.
853 Standard_DivideByZero::NewInstance('')->Jump;
856 #if (!defined (__sun)) && (!defined(SOLARIS))
857 Standard_NumericError::NewInstance("SIGFPE Arithmetic exception detected")->Jump();
862 switch(aSigInfo->si_code) {
863 case FPE_FLTDIV_TRAP :
864 Standard_DivideByZero::NewInstance("Floating Divide By Zero")->Jump();
866 case FPE_INTDIV_TRAP :
867 Standard_DivideByZero::NewInstance("Integer Divide By Zero")->Jump();
869 case FPE_FLTOVF_TRAP :
870 Standard_Overflow::NewInstance("Floating Overflow")->Jump();
872 case FPE_INTOVF_TRAP :
873 Standard_Overflow::NewInstance("Integer Overflow")->Jump();
875 case FPE_FLTUND_TRAP :
876 Standard_NumericError::NewInstance("Floating Underflow")->Jump();
878 case FPE_FLTRES_TRAP:
879 Standard_NumericError::NewInstance("Floating Point Inexact Result")->Jump();
881 case FPE_FLTINV_TRAP :
882 Standard_NumericError::NewInstance("Invalid Floating Point Operation")->Jump();
885 Standard_NumericError::NewInstance("Numeric Error")->Jump();
889 Standard_NumericError::NewInstance("SIGFPE Arithmetic exception detected")->Jump();
893 #if defined (__sgi) || defined(IRIX)
895 sigaddset(&set, SIGTRAP);
896 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
897 Standard_DivideByZero::NewInstance("SIGTRAP IntegerDivideByZero")->Jump(); break;
901 cout << "Unexpected signal " << theSignal << endl ;
907 //============================================================================
909 //============================================================================
912 static void SegvHandler(const int theSignal,
914 const Standard_Address theContext)
916 #ifdef NO_CXX_EXCEPTION
917 if (!Standard_ErrorHandler::IsInTryBlock()) {
918 Handler(theSignal, ip, theContext);
922 (void)theSignal; // silence GCC warnings
927 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
928 //feenableexcept (FE_INVALID | FE_DIVBYZERO);
930 // cout << "OSD::SegvHandler activated(SA_SIGINFO)" << endl ;
934 sigaddset(&set, SIGSEGV);
935 sigprocmask (SIG_UNBLOCK, &set, NULL) ;
936 void *address = ip->si_addr ;
939 sprintf(Msg,"SIGSEGV 'segmentation violation' detected. Address %lx",
941 OSD_SIGSEGV::NewInstance(Msg)->Jump();
946 cout << "Wrong undefined address." << endl ;
952 #elif defined (_hpux) || defined(HPUX)
953 // Not ACTIVE ? SA_SIGINFO is defined on SUN, OSF, SGI and HP (and Linux) !
954 // pour version 09.07
956 static void SegvHandler(const int theSignal,
958 const Standard_Address theContext)
960 unsigned long Space ;
961 unsigned long Offset ;
964 if ( theContext != NULL ) {
965 Space = ((struct sigcontext *)theContext)->sc_sl.sl_ss.ss_cr20 ;
966 Offset = ((struct sigcontext *)theContext)->sc_sl.sl_ss.ss_cr21 ;
967 // cout << "Wrong address = " << hex(Offset) << endl ;
969 sprintf(Msg,"SIGSEGV 'segmentation violation' detected. Address %lx",Offset) ;
970 OSD_SIGSEGV::Jump(Msg);
971 // scp->sc_pcoq_head = scp->sc_pcoq_tail ; Permettrait de continuer a
972 // scp->sc_pcoq_tail = scp->sc_pcoq_tail + 0x4 ; l'intruction suivant le segv.
977 cout << "Wrong undefined address." << endl ;
985 //============================================================================
987 //==== Set the differents signals:
988 //============================================================================
990 void OSD::SetSignal(const Standard_Boolean aFloatingSignal)
992 static int first_time = 3 ;
993 struct sigaction act, oact;
996 if( aFloatingSignal ) {
997 //==== Enable the floating point exceptions ===============
998 #if defined (__sun) || defined (SOLARIS)
999 sigfpe_handler_type PHandler = (sigfpe_handler_type) Handler ;
1000 stat = ieee_handler("set", "invalid", PHandler);
1001 stat = ieee_handler("set", "division", PHandler) || stat;
1002 stat = ieee_handler("set", "overflow", PHandler) || stat;
1004 //stat = ieee_handler("set", "underflow", PHandler) || stat;
1005 //stat = ieee_handler("set", "inexact", PHandler) || stat;
1009 cerr << "ieee_handler does not work !!! KO " << endl;
1012 #elif defined (linux)
1013 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
1014 //feenableexcept (FE_INVALID | FE_DIVBYZERO);
1015 fFltExceptions = Standard_True;
1018 else if ( first_time & 1 ) {
1019 // cout << "SetSignal( Standard_False ) is not implemented..." << endl ;
1020 first_time = first_time & (~ 1) ;
1023 #if defined (sgi) || defined (IRIX )
1024 if ( first_time & 2 ) {
1025 char *TRAP_FPE = getenv("TRAP_FPE") ;
1026 if ( TRAP_FPE == NULL ) {
1028 cout << "On SGI you must set TRAP_FPE environment variable : " << endl ;
1029 cout << "set env(TRAP_FPE) \"UNDERFL=FLUSH_ZERO;OVERFL=DEFAULT;DIVZERO=DEFAULT;INT_OVERFL=DEFAULT\" or" << endl ;
1030 cout << "setenv TRAP_FPE \"UNDERFL=FLUSH_ZERO;OVERFL=DEFAULT;DIVZERO=DEFAULT;INT_OVERFL=DEFAULT\"" << endl ;
1033 first_time = first_time & (~ 2) ;
1038 //==== Save the old Signal Handler, and set the new one ===================
1040 sigemptyset(&act.sa_mask) ;
1043 act.sa_flags = SA_RESTART ;
1048 act.sa_flags = act.sa_flags | SA_SIGINFO ;
1049 act.sa_sigaction = /*(void(*)(int, siginfo_t *, void*))*/ Handler;
1051 act.sa_handler = /*(SIG_PFV)*/ Handler;
1054 //==== Always detected the signal "SIGFPE" =================================
1055 stat = sigaction(SIGFPE,&act,&oact); // ...... floating point exception
1058 cerr << "sigaction does not work !!! KO " << endl;
1060 perror("sigaction ");
1063 //==== Detected the only the "free" signals ================================
1064 sigaction(SIGHUP,&act,&oact); // ...... hangup
1068 sigaction(SIGHUP,&oact,&oact);
1071 sigaction(SIGINT,&act,&oact); // ...... interrupt
1075 sigaction(SIGINT,&oact,&oact);
1078 sigaction(SIGQUIT,&act,&oact); // ...... quit
1082 sigaction(SIGQUIT,&oact,&oact);
1085 sigaction(SIGILL,&act,&oact); // ...... illegal instruction
1089 sigaction(SIGILL,&oact,&oact);
1092 sigaction(SIGBUS,&act,&oact); // ...... bus error
1096 sigaction(SIGBUS,&oact,&oact);
1099 #if (!defined (linux)) && (!defined(__linux__))
1100 sigaction(SIGSYS,&act,&oact); // ...... bad argument to system call
1104 sigaction(SIGSYS,&oact,&oact);
1108 #if defined (__sgi) || defined(IRIX)
1109 sigaction(SIGTRAP,&act,&oact); // Integer Divide By Zero (IRIX)
1113 sigaction(SIGTRAP,&oact,&oact);
1118 act.sa_sigaction = /*(void(*)(int, siginfo_t *, void*))*/ SegvHandler;
1120 act.sa_handler = /*(SIG_PFV)*/ SegvHandler;
1123 if ( sigaction( SIGSEGV , &act , &oact ) ) // ...... segmentation violation
1124 perror("OSD::SetSignal sigaction( SIGSEGV , &act , &oact ) ") ;
1128 sigaction(SIGSEGV,&oact,&oact);
1130 #if defined(__osf__) || defined(DECOSF1)
1131 struct sigaction action, prev_action;
1132 action.sa_handler = SIG_IGN;
1134 action.sa_flags = 0;
1136 if (sigaction (SIGFPE, &action, &prev_action) == -1) {
1137 perror ("sigaction");
1144 //============================================================================
1146 //============================================================================
1148 void OSD :: ControlBreak ()
1151 fCtrlBrk = Standard_False;
1152 OSD_Exception_CTRL_BREAK::Raise ("*** INTERRUPT ***");