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 --------------------------------
33 #ifndef STATUS_FLOAT_MULTIPLE_FAULTS
35 #define STATUS_FLOAT_MULTIPLE_FAULTS (0xC00002B4L)
36 #define STATUS_FLOAT_MULTIPLE_TRAPS (0xC00002B5L)
39 #include <OSD_Exception_ACCESS_VIOLATION.hxx>
40 #include <OSD_Exception_ARRAY_BOUNDS_EXCEEDED.hxx>
41 #include <OSD_Exception_ILLEGAL_INSTRUCTION.hxx>
42 #include <OSD_Exception_IN_PAGE_ERROR.hxx>
43 #include <OSD_Exception_INT_DIVIDE_BY_ZERO.hxx>
44 #include <OSD_Exception_INT_OVERFLOW.hxx>
45 #include <OSD_Exception_INVALID_DISPOSITION.hxx>
46 #include <OSD_Exception_NONCONTINUABLE_EXCEPTION.hxx>
47 #include <OSD_Exception_PRIV_INSTRUCTION.hxx>
48 #include <OSD_Exception_STACK_OVERFLOW.hxx>
49 #include <OSD_Exception_STATUS_NO_MEMORY.hxx>
51 #include <OSD_Environment.hxx>
52 #include <Standard_Underflow.hxx>
53 #include <Standard_ProgramError.hxx>
54 #include <Standard_Mutex.hxx>
56 #include <OSD_WNT.hxx>
67 static Standard_Boolean fCtrlBrk;
69 static Standard_Boolean fMsgBox;
70 static Standard_Boolean fFltExceptions;
72 // used to forbid simultaneous execution of setting / executing handlers
73 static Standard_Mutex THE_SIGNAL_MUTEX;
75 static LONG __fastcall _osd_raise ( DWORD, LPSTR );
76 static BOOL WINAPI _osd_ctrl_break_handler ( DWORD );
78 #if ! defined(OCCT_UWP) && !defined(__MINGW32__) && !defined(__CYGWIN32__)
79 static Standard_Boolean fDbgLoaded;
80 static LONG _osd_debug ( void );
83 //# define _OSD_FPX ( _EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW )
84 # define _OSD_FPX ( _EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW )
86 #ifdef OCC_CONVERT_SIGNALS
87 #define THROW_OR_JUMP(Type,Message) Type::NewInstance(Message)->Jump()
89 #define THROW_OR_JUMP(Type,Message) throw Type(Message)
92 //=======================================================================
93 //function : CallHandler
95 //=======================================================================
96 static LONG CallHandler (DWORD dwExceptionCode,
97 ptrdiff_t ExceptionInformation1,
98 ptrdiff_t ExceptionInformation0)
100 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
102 static wchar_t buffer[2048];
108 // cout << "CallHandler " << dwExceptionCode << endl ;
109 switch ( dwExceptionCode ) {
110 case EXCEPTION_FLT_DENORMAL_OPERAND:
111 // cout << "CallHandler : EXCEPTION_FLT_DENORMAL_OPERAND:" << endl ;
112 StringCchCopyW (buffer, _countof(buffer), L"FLT DENORMAL OPERAND");
115 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
116 // cout << "CallHandler : EXCEPTION_FLT_DIVIDE_BY_ZERO:" << endl ;
117 StringCchCopyW (buffer, _countof(buffer), L"FLT DIVIDE BY ZERO");
120 case EXCEPTION_FLT_INEXACT_RESULT:
121 // cout << "CallHandler : EXCEPTION_FLT_INEXACT_RESULT:" << endl ;
122 StringCchCopyW (buffer, _countof(buffer), L"FLT INEXACT RESULT");
125 case EXCEPTION_FLT_INVALID_OPERATION:
126 // cout << "CallHandler : EXCEPTION_FLT_INVALID_OPERATION:" << endl ;
127 StringCchCopyW (buffer, _countof(buffer), L"FLT INVALID OPERATION");
130 case EXCEPTION_FLT_OVERFLOW:
131 // cout << "CallHandler : EXCEPTION_FLT_OVERFLOW:" << endl ;
132 StringCchCopyW (buffer, _countof(buffer), L"FLT OVERFLOW");
135 case EXCEPTION_FLT_STACK_CHECK:
136 // cout << "CallHandler : EXCEPTION_FLT_STACK_CHECK:" << endl ;
137 StringCchCopyW (buffer, _countof(buffer), L"FLT STACK CHECK");
140 case EXCEPTION_FLT_UNDERFLOW:
141 // cout << "CallHandler : EXCEPTION_FLT_UNDERFLOW:" << endl ;
142 StringCchCopyW (buffer, _countof(buffer), L"FLT UNDERFLOW");
145 case STATUS_FLOAT_MULTIPLE_TRAPS:
146 // cout << "CallHandler : EXCEPTION_FLT_UNDERFLOW:" << endl ;
147 StringCchCopyW (buffer, _countof(buffer), L"FLT MULTIPLE TRAPS (possible overflow in conversion of double to integer)");
150 case STATUS_FLOAT_MULTIPLE_FAULTS:
151 // cout << "CallHandler : EXCEPTION_FLT_UNDERFLOW:" << endl ;
152 StringCchCopyW (buffer, _countof(buffer), L"FLT MULTIPLE FAULTS");
155 case STATUS_NO_MEMORY:
156 // cout << "CallHandler : STATUS_NO_MEMORY:" << endl ;
157 THROW_OR_JUMP (OSD_Exception_STATUS_NO_MEMORY, "MEMORY ALLOCATION ERROR ( no room in the process heap )");
159 case EXCEPTION_ACCESS_VIOLATION:
160 // cout << "CallHandler : EXCEPTION_ACCESS_VIOLATION:" << endl ;
161 StringCchPrintfW (buffer, _countof(buffer), L"%s%s%s0x%.8p%s%s%s", L"ACCESS VIOLATION",
162 fMsgBox ? L"\n" : L" ", L"at address ",
163 ExceptionInformation1 ,
165 ExceptionInformation0 ? L"WRITE" : L"READ",
168 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
169 // cout << "CallHandler : EXCEPTION_ARRAY_BOUNDS_EXCEEDED:" << endl ;
170 StringCchCopyW (buffer, _countof(buffer), L"ARRAY BOUNDS EXCEEDED");
172 case EXCEPTION_DATATYPE_MISALIGNMENT:
173 // cout << "CallHandler : EXCEPTION_DATATYPE_MISALIGNMENT:" << endl ;
174 StringCchCopyW (buffer, _countof(buffer), L"DATATYPE MISALIGNMENT");
177 case EXCEPTION_ILLEGAL_INSTRUCTION:
178 // cout << "CallHandler : EXCEPTION_ILLEGAL_INSTRUCTION:" << endl ;
179 StringCchCopyW (buffer, _countof(buffer), L"ILLEGAL INSTRUCTION");
182 case EXCEPTION_IN_PAGE_ERROR:
183 // cout << "CallHandler : EXCEPTION_IN_PAGE_ERROR:" << endl ;
184 StringCchCopyW (buffer, _countof(buffer), L"IN_PAGE ERROR");
187 case EXCEPTION_INT_DIVIDE_BY_ZERO:
188 // cout << "CallHandler : EXCEPTION_INT_DIVIDE_BY_ZERO:" << endl ;
189 StringCchCopyW (buffer, _countof(buffer), L"INTEGER DIVISION BY ZERO");
192 case EXCEPTION_INT_OVERFLOW:
193 // cout << "CallHandler : EXCEPTION_INT_OVERFLOW:" << endl ;
194 StringCchCopyW (buffer, _countof(buffer), L"INTEGER OVERFLOW");
197 case EXCEPTION_INVALID_DISPOSITION:
198 // cout << "CallHandler : EXCEPTION_INVALID_DISPOSITION:" << endl ;
199 StringCchCopyW (buffer, _countof(buffer), L"INVALID DISPOSITION");
202 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
203 // cout << "CallHandler : EXCEPTION_NONCONTINUABLE_EXCEPTION:" << endl ;
204 StringCchCopyW (buffer, _countof(buffer), L"NONCONTINUABLE EXCEPTION");
207 case EXCEPTION_PRIV_INSTRUCTION:
208 // cout << "CallHandler : EXCEPTION_PRIV_INSTRUCTION:" << endl ;
209 StringCchCopyW (buffer, _countof(buffer), L"PRIVELEGED INSTRUCTION ENCOUNTERED");
212 case EXCEPTION_STACK_OVERFLOW:
213 // cout << "CallHandler : EXCEPTION_STACK_OVERFLOW:" << endl ;
214 #if defined( _MSC_VER ) && ( _MSC_VER >= 1300 ) && !defined(OCCT_UWP)
215 // try recovering from stack overflow: available in MS VC++ 7.0
216 if (!_resetstkoflw())
217 StringCchCopyW (buffer, _countof(buffer), L"Unrecoverable STACK OVERFLOW");
220 StringCchCopyW (buffer, _countof(buffer), L"STACK OVERFLOW");
224 StringCchPrintfW (buffer, _countof(buffer), L"unknown exception code 0x%x, params 0x%p 0x%p",
225 dwExceptionCode, ExceptionInformation1, ExceptionInformation0 );
229 // provide message to the user with possibility to stop
231 StringCchLengthW (buffer, _countof(buffer),&idx);
232 if ( idx && fMsgBox && dwExceptionCode != EXCEPTION_NONCONTINUABLE_EXCEPTION ) {
233 // reset FP operations before message box, otherwise it may fail to show up
237 #if ! defined(OCCT_UWP) && !defined(__MINGW32__) && !defined(__CYGWIN32__)
238 MessageBeep ( MB_ICONHAND );
239 int aChoice = ::MessageBoxW (0, buffer, L"OCCT Exception Handler", MB_ABORTRETRYIGNORE | MB_ICONSTOP);
240 if (aChoice == IDRETRY)
244 } else if (aChoice == IDABORT)
251 if ( !fFltExceptions ) return EXCEPTION_EXECUTE_HANDLER;
254 _controlfp ( 0, _OSD_FPX ) ; // JR add :
255 // cout << "OSD::WntHandler _controlfp( 0, _OSD_FPX ) " << hex << _controlfp(0,0) << dec << endl ;
259 WideCharToMultiByte(CP_UTF8, 0, buffer, -1, aBufferA, sizeof(aBufferA), NULL, NULL);
260 return _osd_raise(dwExceptionCode, aBufferA);
263 //=======================================================================
264 //function : SIGWntHandler
265 //purpose : Will only be used if user calls ::raise() function with
266 // signal type set in OSD::SetSignal() - SIGSEGV, SIGFPE, SIGILL
267 // (the latter will likely be removed in the future)
268 //=======================================================================
269 static void SIGWntHandler (int signum, int sub_code)
271 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
274 if ( signal( signum , (void(*)(int))SIGWntHandler ) == SIG_ERR )
275 cout << "signal error" << endl ;
278 CallHandler( EXCEPTION_FLT_INVALID_OPERATION ,0,0) ;
281 CallHandler( EXCEPTION_FLT_DENORMAL_OPERAND ,0,0) ;
283 case _FPE_ZERODIVIDE :
284 CallHandler( EXCEPTION_FLT_DIVIDE_BY_ZERO ,0,0) ;
287 CallHandler( EXCEPTION_FLT_OVERFLOW ,0,0) ;
289 case _FPE_UNDERFLOW :
290 CallHandler( EXCEPTION_FLT_UNDERFLOW ,0,0) ;
293 CallHandler( EXCEPTION_FLT_INEXACT_RESULT ,0,0) ;
296 cout << "SIGWntHandler(default) -> throw Standard_NumericError(\"Floating Point Error\");" << endl;
297 THROW_OR_JUMP (Standard_NumericError, "Floating Point Error");
302 if ( signal( signum, (void(*)(int))SIGWntHandler ) == SIG_ERR )
303 cout << "signal error" << endl ;
304 CallHandler( EXCEPTION_ACCESS_VIOLATION ,0,0) ;
307 if ( signal( signum, (void(*)(int))SIGWntHandler ) == SIG_ERR )
308 cout << "signal error" << endl ;
309 CallHandler( EXCEPTION_ILLEGAL_INSTRUCTION ,0,0) ;
312 cout << "SIGWntHandler unexpected signal : " << signum << endl ;
320 //=======================================================================
321 //function : TranslateSE
322 //purpose : Translate Structural Exceptions into C++ exceptions
323 // Will be used when user's code is compiled with /EHa option
324 //=======================================================================
326 // If this file compiled with the default MSVC options for exception
327 // handling (/GX or /EHsc) then the following warning is issued:
328 // warning C4535: calling _set_se_translator() requires /EHa
329 // However it is correctly inserted and used when user's code compiled with /EHa.
330 // So, here we disable the warning.
331 #pragma warning (disable:4535)
333 static void TranslateSE( unsigned int theCode, EXCEPTION_POINTERS* theExcPtr )
335 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
336 ptrdiff_t info1 = 0, info0 = 0;
338 info1 = theExcPtr->ExceptionRecord->ExceptionInformation[1];
339 info0 = theExcPtr->ExceptionRecord->ExceptionInformation[0];
341 CallHandler(theCode, info1, info0);
345 //=======================================================================
346 //function : WntHandler
347 //purpose : Will be used when user's code is compiled with /EHs
348 // option and unless user sets his own exception handler with
349 // ::SetUnhandledExceptionFilter().
350 //=======================================================================
351 static LONG WINAPI WntHandler (EXCEPTION_POINTERS *lpXP)
353 DWORD dwExceptionCode = lpXP->ExceptionRecord->ExceptionCode;
355 return CallHandler (dwExceptionCode,
356 lpXP->ExceptionRecord->ExceptionInformation[1],
357 lpXP->ExceptionRecord->ExceptionInformation[0]);
360 //=======================================================================
361 //function : SetSignal
363 //=======================================================================
364 void OSD::SetSignal (const Standard_Boolean theFloatingSignal)
366 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
367 #if !defined(OCCT_UWP) || defined(NTDDI_WIN10_TH2)
368 OSD_Environment env ("CSF_DEBUG_MODE");
369 TCollection_AsciiString val = env.Value();
372 cout << "Environment variable CSF_DEBUG_MODE setted.\n";
373 fMsgBox = Standard_True;
377 fMsgBox = Standard_False;
380 // Set exception handler (ignored when running under debugger). It will be used in most cases
381 // when user's code is compiled with /EHs
382 // Replaces the existing top-level exception filter for all existing and all future threads
383 // in the calling process
384 ::SetUnhandledExceptionFilter (/*(LPTOP_LEVEL_EXCEPTION_FILTER)*/ WntHandler);
385 #endif // NTDDI_WIN10_TH2
387 // Signal handlers will only be used when the method ::raise() will be used
388 // Handlers must be set for every thread
389 if (signal (SIGSEGV, (void(*)(int))SIGWntHandler) == SIG_ERR)
390 cout << "signal(OSD::SetSignal) error\n";
391 if (signal (SIGFPE, (void(*)(int))SIGWntHandler) == SIG_ERR)
392 cout << "signal(OSD::SetSignal) error\n";
393 if (signal (SIGILL, (void(*)(int))SIGWntHandler) == SIG_ERR)
394 cout << "signal(OSD::SetSignal) error\n";
396 // Set Ctrl-C and Ctrl-Break handler
397 fCtrlBrk = Standard_False;
399 SetConsoleCtrlHandler (&_osd_ctrl_break_handler, TRUE);
402 // _se_translator_function pOldSeFunc =
403 _set_se_translator (TranslateSE);
406 fFltExceptions = theFloatingSignal;
407 if (theFloatingSignal)
409 _controlfp (0, _OSD_FPX); // JR add :
412 _controlfp (_OSD_FPX, _OSD_FPX); // JR add :
414 } // end OSD :: SetSignal
416 //============================================================================
418 //============================================================================
419 void OSD::ControlBreak () {
421 fCtrlBrk = Standard_False;
422 throw OSD_Exception_CTRL_BREAK ( "*** INTERRUPT ***" );
424 } // end OSD :: ControlBreak
427 //============================================================================
428 //==== _osd_ctrl_break_handler
429 //============================================================================
430 static BOOL WINAPI _osd_ctrl_break_handler ( DWORD dwCode ) {
431 if ( dwCode == CTRL_C_EVENT || dwCode == CTRL_BREAK_EVENT ) {
432 MessageBeep ( MB_ICONEXCLAMATION );
433 fCtrlBrk = Standard_True;
438 } // end _osd_ctrl_break_handler
441 //============================================================================
443 //============================================================================
444 static LONG __fastcall _osd_raise ( DWORD dwCode, LPSTR msg )
446 if (msg[0] == '\x03') ++msg;
450 case EXCEPTION_ACCESS_VIOLATION:
451 THROW_OR_JUMP (OSD_Exception_ACCESS_VIOLATION, msg);
453 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
454 THROW_OR_JUMP (OSD_Exception_ARRAY_BOUNDS_EXCEEDED, msg);
456 case EXCEPTION_DATATYPE_MISALIGNMENT:
457 THROW_OR_JUMP (Standard_ProgramError, msg);
459 case EXCEPTION_ILLEGAL_INSTRUCTION:
460 THROW_OR_JUMP (OSD_Exception_ILLEGAL_INSTRUCTION, msg);
462 case EXCEPTION_IN_PAGE_ERROR:
463 THROW_OR_JUMP (OSD_Exception_IN_PAGE_ERROR, msg);
465 case EXCEPTION_INT_DIVIDE_BY_ZERO:
466 THROW_OR_JUMP (Standard_DivideByZero, msg);
468 case EXCEPTION_INT_OVERFLOW:
469 THROW_OR_JUMP (OSD_Exception_INT_OVERFLOW, msg);
471 case EXCEPTION_INVALID_DISPOSITION:
472 THROW_OR_JUMP (OSD_Exception_INVALID_DISPOSITION, msg);
474 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
475 THROW_OR_JUMP (OSD_Exception_NONCONTINUABLE_EXCEPTION, msg);
477 case EXCEPTION_PRIV_INSTRUCTION:
478 THROW_OR_JUMP (OSD_Exception_PRIV_INSTRUCTION, msg);
480 case EXCEPTION_STACK_OVERFLOW:
481 THROW_OR_JUMP (OSD_Exception_STACK_OVERFLOW, msg);
483 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
484 THROW_OR_JUMP (Standard_DivideByZero, msg);
486 case EXCEPTION_FLT_STACK_CHECK:
487 case EXCEPTION_FLT_OVERFLOW:
488 THROW_OR_JUMP (Standard_Overflow, msg);
490 case EXCEPTION_FLT_UNDERFLOW:
491 THROW_OR_JUMP (Standard_Underflow, msg);
493 case EXCEPTION_FLT_INVALID_OPERATION:
494 case EXCEPTION_FLT_DENORMAL_OPERAND:
495 case EXCEPTION_FLT_INEXACT_RESULT:
496 case STATUS_FLOAT_MULTIPLE_TRAPS:
497 case STATUS_FLOAT_MULTIPLE_FAULTS:
498 THROW_OR_JUMP (Standard_NumericError, msg);
503 return EXCEPTION_EXECUTE_HANDLER;
506 #if ! defined(OCCT_UWP) && !defined(__MINGW32__) && !defined(__CYGWIN32__)
507 //============================================================================
509 //============================================================================
510 LONG _osd_debug ( void ) {
517 HANDLE hEvent = INVALID_HANDLE_VALUE;
520 TCHAR keyValue[ MAX_PATH ];
521 TCHAR cmdLine[ MAX_PATH ];
522 SECURITY_ATTRIBUTES sa;
523 PROCESS_INFORMATION pi;
530 TEXT( "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug" ),
535 dwValueLen = sizeof ( keyValue );
537 if ( RegQueryValueEx (
538 hKey, TEXT( "Debugger" ), NULL, &dwKeyType, ( unsigned char* )keyValue, &dwValueLen
542 sa.nLength = sizeof ( SECURITY_ATTRIBUTES );
543 sa.lpSecurityDescriptor = NULL;
544 sa.bInheritHandle = TRUE;
546 if ( ( hEvent = CreateEvent ( &sa, TRUE, FALSE, NULL ) ) == NULL ) __leave;
548 StringCchPrintf(cmdLine, _countof(cmdLine), keyValue, GetCurrentProcessId(), hEvent);
550 ZeroMemory ( &si, sizeof ( STARTUPINFO ) );
552 si.cb = sizeof ( STARTUPINFO );
553 si.dwFlags = STARTF_FORCEONFEEDBACK;
555 // cout << "_osd_debug -> CreateProcess" << endl ;
556 if ( !CreateProcess (
557 NULL, cmdLine, NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE,
562 // cout << "_osd_debug -> WaitForSingleObject " << endl ;
563 WaitForSingleObject ( hEvent, INFINITE );
564 // cout << "_osd_debug <- WaitForSingleObject -> CloseHandle " << endl ;
566 CloseHandle ( pi.hProcess );
567 CloseHandle ( pi.hThread );
569 // cout << "_osd_debug fDbgLoaded " << endl ;
576 // cout << "_osd_debug -> CloseHandle(hKey) " << endl ;
577 if ( hKey != INVALID_HANDLE_VALUE ) CloseHandle ( hKey );
578 // cout << "_osd_debug -> CloseHandle(hEvent) " << endl ;
579 if ( hEvent != INVALID_HANDLE_VALUE ) CloseHandle ( hEvent );
580 // cout << "_osd_debug end __finally " << endl ;
586 action = fDbgLoaded ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER;
587 // cout << "_osd_debug return " << action << " EXCEPTION_CONTINUE_EXECUTION("
588 // << EXCEPTION_CONTINUE_EXECUTION << ")" << endl ;
592 #endif /* ! OCCT_UWP && ! __CYGWIN__ && ! __MINGW32__ */
596 //---------- All Systems except Windows NT : ----------------------------------
600 #include <OSD_WhoAmI.hxx>
601 #include <OSD_SIGHUP.hxx>
602 #include <OSD_SIGINT.hxx>
603 #include <OSD_SIGQUIT.hxx>
604 #include <OSD_SIGILL.hxx>
605 #include <OSD_SIGKILL.hxx>
606 #include <OSD_SIGBUS.hxx>
607 #include <OSD_SIGSEGV.hxx>
608 #include <OSD_SIGSYS.hxx>
609 #include <Standard_NumericError.hxx>
611 #include <Standard_ErrorHandler.hxx>
619 static Standard_Boolean fFltExceptions = Standard_False;
622 // variable signalling that Control-C has been pressed (SIGINT signal)
623 static Standard_Boolean fCtrlBrk;
625 //const OSD_WhoAmI Iam = OSD_WPackage;
627 typedef void (ACT_SIGIO_HANDLER)(void) ;
628 ACT_SIGIO_HANDLER *ADR_ACT_SIGIO_HANDLER = NULL ;
631 typedef void (* SIG_PFV) (int);
640 # include <sys/siginfo.h>
644 typedef void (* SIG_PFV) (int);
648 #if !defined(__ANDROID__) && !defined(__QNX__)
649 #include <sys/signal.h>
652 //============================================================================
654 //==== Catche the differents signals:
655 //==== 1- The Fatal signals, which cause the end of process:
656 //==== 2- The exceptions which are "signaled" by Raise.
657 //==== The Fatal Signals:
658 //==== SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGKILL, SIGBUS, SIGSYS
659 //==== The Exceptions:
661 //==== (SUN versions)
662 //==== FPE_INTOVF_TRAP // ..... integer overflow
663 //==== FPE_INTDIV_TRAP // ..... integer divide by zero
664 //==== FPE_FLTINEX_TRAP // ..... [floating inexact result]
665 //==== FPE_FLTDIV_TRAP // ..... [floating divide by zero]
666 //==== FPE_FLTUND_TRAP // ..... [floating underflow]
667 //==== FPE_FLTOPER_TRAP // ..... [floating inexact result]
668 //==== FPE_FLTOVF_TRAP // ..... [floating overflow]
669 //==== SIGSEGV is handled by "SegvHandler()"
670 //============================================================================
672 static void Handler (const int theSignal, siginfo_t */*theSigInfo*/, const Standard_Address /*theContext*/)
674 static void Handler (const int theSignal)
677 struct sigaction oldact, act;
678 // re-install the signal
679 if ( ! sigaction (theSignal, NULL, &oldact) ) {
680 // cout << " signal is " << theSignal << " handler is " << oldact.sa_handler << endl;
681 if (sigaction (theSignal, &oldact, &act)) perror ("sigaction");
684 perror ("sigaction");
687 // cout << "OSD::Handler: signal " << (int) theSignal << " occured inside a try block " << endl ;
688 if ( ADR_ACT_SIGIO_HANDLER != NULL )
689 (*ADR_ACT_SIGIO_HANDLER)() ;
692 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
693 //feenableexcept (FE_INVALID | FE_DIVBYZERO);
699 OSD_SIGHUP::NewInstance("SIGHUP 'hangup' detected.")->Jump();
703 // For safe handling of Control-C as stop event, arm a variable but do not
704 // generate longjump (we are out of context anyway)
705 fCtrlBrk = Standard_True;
706 // OSD_SIGINT::NewInstance("SIGINT 'interrupt' detected.")->Jump();
710 OSD_SIGQUIT::NewInstance("SIGQUIT 'quit' detected.")->Jump();
714 OSD_SIGILL::NewInstance("SIGILL 'illegal instruction' detected.")->Jump();
718 OSD_SIGKILL::NewInstance("SIGKILL 'kill' detected.")->Jump();
722 sigaddset(&set, SIGBUS);
723 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
724 OSD_SIGBUS::NewInstance("SIGBUS 'bus error' detected.")->Jump();
728 OSD_SIGSEGV::NewInstance("SIGSEGV 'segmentation violation' detected.")->Jump();
733 OSD_SIGSYS::NewInstance("SIGSYS 'bad argument to system call' detected.")->Jump();
738 sigaddset(&set, SIGFPE);
739 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
741 // Pour DEC/OSF1 SIGFPE = Division par zero.
742 Standard_DivideByZero::NewInstance('')->Jump;
745 #if (!defined (__sun)) && (!defined(SOLARIS))
746 Standard_NumericError::NewInstance("SIGFPE Arithmetic exception detected")->Jump();
751 switch(aSigInfo->si_code) {
752 case FPE_FLTDIV_TRAP :
753 Standard_DivideByZero::NewInstance("Floating Divide By Zero")->Jump();
755 case FPE_INTDIV_TRAP :
756 Standard_DivideByZero::NewInstance("Integer Divide By Zero")->Jump();
758 case FPE_FLTOVF_TRAP :
759 Standard_Overflow::NewInstance("Floating Overflow")->Jump();
761 case FPE_INTOVF_TRAP :
762 Standard_Overflow::NewInstance("Integer Overflow")->Jump();
764 case FPE_FLTUND_TRAP :
765 Standard_NumericError::NewInstance("Floating Underflow")->Jump();
767 case FPE_FLTRES_TRAP:
768 Standard_NumericError::NewInstance("Floating Point Inexact Result")->Jump();
770 case FPE_FLTINV_TRAP :
771 Standard_NumericError::NewInstance("Invalid Floating Point Operation")->Jump();
774 Standard_NumericError::NewInstance("Numeric Error")->Jump();
778 Standard_NumericError::NewInstance("SIGFPE Arithmetic exception detected")->Jump();
782 #if defined (__sgi) || defined(IRIX)
784 sigaddset(&set, SIGTRAP);
785 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
786 Standard_DivideByZero::NewInstance("SIGTRAP IntegerDivideByZero")->Jump(); break;
790 cout << "Unexpected signal " << theSignal << endl ;
796 //============================================================================
798 //============================================================================
801 static void SegvHandler(const int theSignal,
803 const Standard_Address theContext)
805 (void)theSignal; // silence GCC warnings
810 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
811 //feenableexcept (FE_INVALID | FE_DIVBYZERO);
813 // cout << "OSD::SegvHandler activated(SA_SIGINFO)" << endl ;
817 sigaddset(&set, SIGSEGV);
818 sigprocmask (SIG_UNBLOCK, &set, NULL) ;
819 void *address = ip->si_addr ;
822 sprintf(Msg,"SIGSEGV 'segmentation violation' detected. Address %lx",
824 OSD_SIGSEGV::NewInstance(Msg)->Jump();
829 cout << "Wrong undefined address." << endl ;
835 #elif defined (_hpux) || defined(HPUX)
836 // Not ACTIVE ? SA_SIGINFO is defined on SUN, OSF, SGI and HP (and Linux) !
837 // pour version 09.07
839 static void SegvHandler(const int theSignal,
841 const Standard_Address theContext)
843 unsigned long Space ;
844 unsigned long Offset ;
847 if ( theContext != NULL ) {
848 Space = ((struct sigcontext *)theContext)->sc_sl.sl_ss.ss_cr20 ;
849 Offset = ((struct sigcontext *)theContext)->sc_sl.sl_ss.ss_cr21 ;
850 // cout << "Wrong address = " << hex(Offset) << endl ;
852 sprintf(Msg,"SIGSEGV 'segmentation violation' detected. Address %lx",Offset) ;
853 OSD_SIGSEGV::Jump(Msg);
854 // scp->sc_pcoq_head = scp->sc_pcoq_tail ; Permettrait de continuer a
855 // scp->sc_pcoq_tail = scp->sc_pcoq_tail + 0x4 ; l'intruction suivant le segv.
860 cout << "Wrong undefined address." << endl ;
868 //============================================================================
870 //==== Set the differents signals:
871 //============================================================================
873 void OSD::SetSignal(const Standard_Boolean aFloatingSignal)
875 struct sigaction act, oact;
878 if( aFloatingSignal ) {
879 //==== Enable the floating point exceptions ===============
880 #if defined (__sun) || defined (SOLARIS)
881 sigfpe_handler_type PHandler = (sigfpe_handler_type) Handler ;
882 stat = ieee_handler("set", "invalid", PHandler);
883 stat = ieee_handler("set", "division", PHandler) || stat;
884 stat = ieee_handler("set", "overflow", PHandler) || stat;
886 //stat = ieee_handler("set", "underflow", PHandler) || stat;
887 //stat = ieee_handler("set", "inexact", PHandler) || stat;
891 cerr << "ieee_handler does not work !!! KO " << endl;
894 #elif defined (__linux__)
895 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
896 fFltExceptions = Standard_True;
901 #if defined (__linux__)
902 fedisableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
903 fFltExceptions = Standard_False;
907 #if defined (sgi) || defined (IRIX )
908 char *TRAP_FPE = getenv("TRAP_FPE") ;
909 if ( TRAP_FPE == NULL ) {
911 cout << "On SGI you must set TRAP_FPE environment variable : " << endl ;
912 cout << "set env(TRAP_FPE) \"UNDERFL=FLUSH_ZERO;OVERFL=DEFAULT;DIVZERO=DEFAULT;INT_OVERFL=DEFAULT\" or" << endl ;
913 cout << "setenv TRAP_FPE \"UNDERFL=FLUSH_ZERO;OVERFL=DEFAULT;DIVZERO=DEFAULT;INT_OVERFL=DEFAULT\"" << endl ;
918 //==== Save the old Signal Handler, and set the new one ===================
920 sigemptyset(&act.sa_mask) ;
923 act.sa_flags = SA_RESTART ;
928 act.sa_flags = act.sa_flags | SA_SIGINFO ;
929 act.sa_sigaction = /*(void(*)(int, siginfo_t *, void*))*/ Handler;
931 act.sa_handler = /*(SIG_PFV)*/ Handler;
934 //==== Always detected the signal "SIGFPE" =================================
935 stat = sigaction(SIGFPE,&act,&oact); // ...... floating point exception
938 cerr << "sigaction does not work !!! KO " << endl;
940 perror("sigaction ");
943 //==== Detected the only the "free" signals ================================
944 sigaction(SIGHUP,&act,&oact); // ...... hangup
948 sigaction(SIGHUP,&oact,&oact);
951 sigaction(SIGINT,&act,&oact); // ...... interrupt
955 sigaction(SIGINT,&oact,&oact);
958 sigaction(SIGQUIT,&act,&oact); // ...... quit
962 sigaction(SIGQUIT,&oact,&oact);
965 sigaction(SIGILL,&act,&oact); // ...... illegal instruction
969 sigaction(SIGILL,&oact,&oact);
972 sigaction(SIGBUS,&act,&oact); // ...... bus error
976 sigaction(SIGBUS,&oact,&oact);
979 #if !defined(__linux__)
980 sigaction(SIGSYS,&act,&oact); // ...... bad argument to system call
984 sigaction(SIGSYS,&oact,&oact);
988 #if defined (__sgi) || defined(IRIX)
989 sigaction(SIGTRAP,&act,&oact); // Integer Divide By Zero (IRIX)
993 sigaction(SIGTRAP,&oact,&oact);
998 act.sa_sigaction = /*(void(*)(int, siginfo_t *, void*))*/ SegvHandler;
1000 act.sa_handler = /*(SIG_PFV)*/ SegvHandler;
1003 if ( sigaction( SIGSEGV , &act , &oact ) ) // ...... segmentation violation
1004 perror("OSD::SetSignal sigaction( SIGSEGV , &act , &oact ) ") ;
1008 sigaction(SIGSEGV,&oact,&oact);
1010 #if defined(__osf__) || defined(DECOSF1)
1011 struct sigaction action, prev_action;
1012 action.sa_handler = SIG_IGN;
1014 action.sa_flags = 0;
1016 if (sigaction (SIGFPE, &action, &prev_action) == -1) {
1017 perror ("sigaction");
1024 //============================================================================
1026 //============================================================================
1028 void OSD :: ControlBreak ()
1031 fCtrlBrk = Standard_False;
1032 throw OSD_Exception_CTRL_BREAK ("*** INTERRUPT ***");