1 // Copyright (c) 1999-2012 OPEN CASCADE SAS
3 // The content of this file is subject to the Open CASCADE Technology Public
4 // License Version 6.5 (the "License"). You may not use the content of this file
5 // except in compliance with the License. Please obtain a copy of the License
6 // at http://www.opencascade.org and read it completely before using this file.
8 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
9 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11 // The Original Code and all software distributed under the License is
12 // distributed on an "AS IS" basis, without warranty of any kind, and the
13 // Initial Developer hereby disclaims all such warranties, including without
14 // limitation, any warranties of merchantability, fitness for a particular
15 // purpose or non-infringement. Please see the License for the specific terms
16 // and conditions governing the rights and limitations under the License.
23 //---------------------------- Windows NT System --------------------------------
31 #include <OSD_Exception_ACCESS_VIOLATION.hxx>
32 #include <OSD_Exception_ARRAY_BOUNDS_EXCEEDED.hxx>
33 #include <OSD_Exception_ILLEGAL_INSTRUCTION.hxx>
34 #include <OSD_Exception_IN_PAGE_ERROR.hxx>
35 #include <OSD_Exception_INT_DIVIDE_BY_ZERO.hxx>
36 #include <OSD_Exception_INT_OVERFLOW.hxx>
37 #include <OSD_Exception_INVALID_DISPOSITION.hxx>
38 #include <OSD_Exception_NONCONTINUABLE_EXCEPTION.hxx>
39 #include <OSD_Exception_PRIV_INSTRUCTION.hxx>
40 #include <OSD_Exception_STACK_OVERFLOW.hxx>
41 #include <OSD_Exception_STATUS_NO_MEMORY.hxx>
42 #include <OSD_Exception_CTRL_BREAK.hxx>
44 #include <OSD_Environment.hxx>
45 #include <Standard_Underflow.hxx>
46 #include <Standard_DivideByZero.hxx>
47 #include <Standard_Overflow.hxx>
48 #include <Standard_ProgramError.hxx>
49 #include <Standard_Mutex.hxx>
51 #include <OSD_WNT_1.hxx>
62 static Standard_Boolean fMsgBox;
63 static Standard_Boolean fFltExceptions;
64 static Standard_Boolean fDbgLoaded;
65 static Standard_Boolean fCtrlBrk;
67 // used to forbid simultaneous execution of setting / executing handlers
68 static Standard_Mutex THE_SIGNAL_MUTEX;
70 static LONG __fastcall _osd_raise ( DWORD, LPTSTR );
71 static BOOL WINAPI _osd_ctrl_break_handler ( DWORD );
73 extern "C" Standard_EXPORT LONG _osd_debug ( void );
75 MB_DESC fatalErrorDesc[] = {
77 { MBT_ICON, ( int )IDI_HAND },
78 { MBT_BUTTON, IDYES, TEXT( "Continue" ) },
79 { MBT_BUTTON, IDNO, TEXT( "Debugger" ) },
80 { MBT_BUTTON, IDCANCEL, TEXT( "Stop" ) }
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)
96 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
98 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
99 static TCHAR buffer[ 2048 ];
104 // cout << "CallHandler " << dwExceptionCode << endl ;
105 switch ( dwExceptionCode ) {
107 case EXCEPTION_FLT_DENORMAL_OPERAND:
108 // cout << "CallHandler : EXCEPTION_FLT_DENORMAL_OPERAND:" << endl ;
109 lstrcpy ( buffer, TEXT( "FLT DENORMAL OPERAND" ) );
112 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
113 // cout << "CallHandler : EXCEPTION_FLT_DIVIDE_BY_ZERO:" << endl ;
114 lstrcpy ( buffer, TEXT( "FLT DIVIDE BY ZERO" ) );
117 case EXCEPTION_FLT_INEXACT_RESULT:
118 // cout << "CallHandler : EXCEPTION_FLT_INEXACT_RESULT:" << endl ;
119 lstrcpy ( buffer, TEXT( "FLT INEXACT RESULT" ) );
122 case EXCEPTION_FLT_INVALID_OPERATION:
123 // cout << "CallHandler : EXCEPTION_FLT_INVALID_OPERATION:" << endl ;
124 lstrcpy ( buffer, TEXT( "FLT INVALID OPERATION" ) );
127 case EXCEPTION_FLT_OVERFLOW:
128 // cout << "CallHandler : EXCEPTION_FLT_OVERFLOW:" << endl ;
129 lstrcpy ( buffer, TEXT( "FLT OVERFLOW" ) );
132 case EXCEPTION_FLT_STACK_CHECK:
133 // cout << "CallHandler : EXCEPTION_FLT_STACK_CHECK:" << endl ;
134 lstrcpy ( buffer, TEXT( "FLT STACK CHECK" ) );
137 case EXCEPTION_FLT_UNDERFLOW:
138 // cout << "CallHandler : EXCEPTION_FLT_UNDERFLOW:" << endl ;
139 lstrcpy ( buffer, TEXT( "FLT UNDERFLOW" ) );
142 case STATUS_FLOAT_MULTIPLE_TRAPS:
143 // cout << "CallHandler : EXCEPTION_FLT_UNDERFLOW:" << endl ;
144 lstrcpy ( buffer, TEXT( "FLT MULTIPLE TRAPS (possible overflow in conversion of double to integer)" ) );
147 case STATUS_FLOAT_MULTIPLE_FAULTS:
148 // cout << "CallHandler : EXCEPTION_FLT_UNDERFLOW:" << endl ;
149 lstrcpy ( buffer, TEXT( "FLT MULTIPLE FAULTS" ) );
153 case STATUS_NO_MEMORY:
154 // cout << "CallHandler : STATUS_NO_MEMORY:" << endl ;
155 OSD_Exception_STATUS_NO_MEMORY ::
156 Raise ( TEXT( "MEMORY ALLOCATION ERROR ( no room in the process heap )" ) );
158 case EXCEPTION_ACCESS_VIOLATION:
159 // cout << "CallHandler : EXCEPTION_ACCESS_VIOLATION:" << endl ;
160 wsprintf ( buffer, TEXT( "%s%s%s0x%.8p%s%s%s" ), TEXT( "ACCESS VIOLATION" ),
161 fMsgBox ? "\n" : " ", TEXT( "at address " ),
162 ExceptionInformation1 ,
164 ExceptionInformation0 ? TEXT( "WRITE" ) : TEXT( "READ" ),
165 TEXT( "' operation" ));
168 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
169 // cout << "CallHandler : EXCEPTION_ARRAY_BOUNDS_EXCEEDED:" << endl ;
170 lstrcpy ( buffer, TEXT( "ARRAY BOUNDS EXCEEDED" ) );
173 case EXCEPTION_DATATYPE_MISALIGNMENT:
174 // cout << "CallHandler : EXCEPTION_DATATYPE_MISALIGNMENT:" << endl ;
175 lstrcpy ( buffer, TEXT( "DATATYPE MISALIGNMENT" ) );
178 case EXCEPTION_ILLEGAL_INSTRUCTION:
179 // cout << "CallHandler : EXCEPTION_ILLEGAL_INSTRUCTION:" << endl ;
180 lstrcpy ( buffer, TEXT( "ILLEGAL INSTRUCTION" ) );
183 case EXCEPTION_IN_PAGE_ERROR:
184 // cout << "CallHandler : EXCEPTION_IN_PAGE_ERROR:" << endl ;
185 lstrcpy ( buffer, TEXT( "IN_PAGE ERROR" ) );
188 case EXCEPTION_INT_DIVIDE_BY_ZERO:
189 // cout << "CallHandler : EXCEPTION_INT_DIVIDE_BY_ZERO:" << endl ;
190 lstrcpy ( buffer, TEXT( "INTEGER DIVISION BY ZERO" ) );
193 case EXCEPTION_INT_OVERFLOW:
194 // cout << "CallHandler : EXCEPTION_INT_OVERFLOW:" << endl ;
195 lstrcpy ( buffer, TEXT( "INTEGER OVERFLOW" ) );
198 case EXCEPTION_INVALID_DISPOSITION:
199 // cout << "CallHandler : EXCEPTION_INVALID_DISPOSITION:" << endl ;
200 lstrcpy ( buffer, TEXT( "INVALID DISPOSITION" ) );
203 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
204 // cout << "CallHandler : EXCEPTION_NONCONTINUABLE_EXCEPTION:" << endl ;
205 lstrcpy ( buffer, TEXT( "NONCONTINUABLE EXCEPTION" ) );
208 case EXCEPTION_PRIV_INSTRUCTION:
209 // cout << "CallHandler : EXCEPTION_PRIV_INSTRUCTION:" << endl ;
210 lstrcpy ( buffer, TEXT( "PRIVELEGED INSTRUCTION ENCOUNTERED" ) );
213 case EXCEPTION_STACK_OVERFLOW:
214 // cout << "CallHandler : EXCEPTION_STACK_OVERFLOW:" << endl ;
215 #if defined( _MSC_VER ) && ( _MSC_VER >= 1300 )
216 // try recovering from stack overflow: available in MS VC++ 7.0
217 if (!_resetstkoflw())
218 lstrcpy ( buffer, TEXT( "Unrecoverable STACK OVERFLOW" ) );
221 lstrcpy ( buffer, TEXT( "STACK OVERFLOW" ) );
225 wsprintf( buffer, TEXT("unknown exception code 0x%x, params 0x%p 0x%p"),
226 dwExceptionCode, ExceptionInformation1, ExceptionInformation0 );
230 int idx = lstrlen ( buffer );
233 if ( idx && fMsgBox && dwExceptionCode != EXCEPTION_NONCONTINUABLE_EXCEPTION ) {
234 // reset FP operations before message box, otherwise it may fail to show up
238 MessageBeep ( MB_ICONHAND );
239 int msgID = MsgBox ( NULL, buffer, TEXT( "Error detected" ), 4, fatalErrorDesc );
240 // cout << "flterr" << flterr << " fFltExceptions " << fFltExceptions << endl ;
242 if ( !fFltExceptions )
243 return EXCEPTION_EXECUTE_HANDLER;
246 _controlfp ( 0, _OSD_FPX ) ; // JR add :
247 // cout << "OSD::WntHandler _controlfp( 0, _OSD_FPX ) " << hex << _controlfp(0,0) << dec << endl ;
252 PTCHAR ptr = _tcschr ( buffer, TEXT( '\n' ) );
255 // cout << "CallHandler " << dwExceptionCode << endl ;
256 _osd_raise ( dwExceptionCode, buffer );
260 action = _osd_debug ();
261 // cout << "return from CallHandler -> DebugBreak " << endl ;
263 _osd_raise ( dwExceptionCode, buffer );
264 // cout << "CallHandler return : " << action << endl ;
272 if ( !fFltExceptions )
273 return EXCEPTION_EXECUTE_HANDLER;
276 _controlfp ( 0, _OSD_FPX ) ; // JR add :
277 // cout << "OSD::WntHandler _controlfp( 0, _OSD_FPX ) " << hex << _controlfp(0,0) << dec << endl ;
280 return _osd_raise ( dwExceptionCode, buffer );
286 //=======================================================================
287 //function : SIGWntHandler
288 //purpose : Will only be used if user calls ::raise() function with
289 // signal type set in OSD::SetSignal() - SIGSEGV, SIGFPE, SIGILL
290 // (the latter will likely be removed in the future)
291 //=======================================================================
292 static void SIGWntHandler (int signum, int sub_code)
294 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
295 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
298 if ( signal( signum , ( void (*)(int) ) &SIGWntHandler ) == SIG_ERR )
299 cout << "signal error" << endl ;
302 CallHandler( EXCEPTION_FLT_INVALID_OPERATION ,0,0) ;
305 CallHandler( EXCEPTION_FLT_DENORMAL_OPERAND ,0,0) ;
307 case _FPE_ZERODIVIDE :
308 CallHandler( EXCEPTION_FLT_DIVIDE_BY_ZERO ,0,0) ;
311 CallHandler( EXCEPTION_FLT_OVERFLOW ,0,0) ;
313 case _FPE_UNDERFLOW :
314 CallHandler( EXCEPTION_FLT_UNDERFLOW ,0,0) ;
317 CallHandler( EXCEPTION_FLT_INEXACT_RESULT ,0,0) ;
320 cout << "SIGWntHandler(default) -> Standard_NumericError::Raise(\"Floating Point Error\");"
322 Standard_NumericError::Raise("Floating Point Error");
327 if ( signal( signum , ( void (*)(int) ) &SIGWntHandler ) == SIG_ERR )
328 cout << "signal error" << endl ;
329 CallHandler( EXCEPTION_ACCESS_VIOLATION ,0,0) ;
332 if ( signal( signum , ( void (*)(int) ) &SIGWntHandler ) == SIG_ERR )
333 cout << "signal error" << endl ;
334 CallHandler( EXCEPTION_ILLEGAL_INSTRUCTION ,0,0) ;
337 cout << "SIGWntHandler unexpected signal : "
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 Standard_Integer OSD::WntHandler (const Standard_Address theExceptionInfo)
353 LPEXCEPTION_POINTERS lpXP = (LPEXCEPTION_POINTERS )theExceptionInfo;
354 DWORD dwExceptionCode = lpXP->ExceptionRecord->ExceptionCode;
356 return CallHandler (dwExceptionCode,
357 lpXP->ExceptionRecord->ExceptionInformation[1],
358 lpXP->ExceptionRecord->ExceptionInformation[0]);
361 //=======================================================================
362 //function : TranslateSE
363 //purpose : Translate Structural Exceptions into C++ exceptions
364 // Will be used when user's code is compiled with /EHa option
365 //=======================================================================
368 // If this file compiled with the default MSVC options for exception
369 // handling (/GX or /EHsc) then the following warning is issued:
370 // warning C4535: calling _set_se_translator() requires /EHa
371 // However it is correctly inserted and used when user's code compiled with /EHa.
372 // So, here we disable the warning.
373 #pragma warning (disable:4535)
375 static void TranslateSE( unsigned int theCode, EXCEPTION_POINTERS* theExcPtr )
377 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
378 ptrdiff_t info1 = 0, info0 = 0;
380 info1 = theExcPtr->ExceptionRecord->ExceptionInformation[1];
381 info0 = theExcPtr->ExceptionRecord->ExceptionInformation[0];
383 CallHandler(theCode, info1, info0);
387 //=======================================================================
388 //function : SetSignal
390 //=======================================================================
391 void OSD::SetSignal (const Standard_Boolean theFloatingSignal)
393 #if !defined(__CYGWIN32__) && !defined(__MINGW32__)
394 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
395 LPTOP_LEVEL_EXCEPTION_FILTER aPreviousFilter;
397 OSD_Environment env (TEXT("CSF_DEBUG_MODE"));
398 TCollection_AsciiString val = env.Value();
401 cout << "Environment variable CSF_DEBUG_MODE setted.\n";
402 fMsgBox = Standard_True;
406 fMsgBox = Standard_False;
409 // Set exception handler (ignored when running under debugger). It will be used in most cases
410 // when user's code is compiled with /EHs
411 // Replaces the existing top-level exception filter for all existing and all future threads
412 // in the calling process
413 aPreviousFilter = ::SetUnhandledExceptionFilter ((LPTOP_LEVEL_EXCEPTION_FILTER )&OSD::WntHandler);
415 // Signal handlers will only be used when the method ::raise() will be used
416 // Handlers must be set for every thread
417 if (signal (SIGSEGV, (void (*)(int ) )&SIGWntHandler) == SIG_ERR)
418 cout << "signal(OSD::SetSignal) error\n";
419 if (signal (SIGFPE, (void (*)(int ) )&SIGWntHandler) == SIG_ERR)
420 cout << "signal(OSD::SetSignal) error\n";
421 if (signal (SIGILL, (void (*)(int ) )&SIGWntHandler) == SIG_ERR)
422 cout << "signal(OSD::SetSignal) error\n";
424 // Set Ctrl-C and Ctrl-Break handler
425 fCtrlBrk = Standard_False;
426 SetConsoleCtrlHandler (&_osd_ctrl_break_handler, TRUE);
429 _se_translator_function pOldSeFunc = _set_se_translator (TranslateSE);
432 fFltExceptions = theFloatingSignal;
433 if (theFloatingSignal)
435 _controlfp (0, _OSD_FPX); // JR add :
438 _controlfp (_OSD_FPX, _OSD_FPX); // JR add :
441 } // end OSD :: SetSignal
443 //============================================================================
445 //============================================================================
447 void OSD :: ControlBreak () {
451 fCtrlBrk = Standard_False;
452 OSD_Exception_CTRL_BREAK :: Raise ( TEXT( "*** INTERRUPT ***" ) );
456 } // end OSD :: ControlBreak
458 //============================================================================
459 //==== _osd_ctrl_break_handler
460 //============================================================================
462 static BOOL WINAPI _osd_ctrl_break_handler ( DWORD dwCode ) {
464 if ( dwCode == CTRL_C_EVENT || dwCode == CTRL_BREAK_EVENT ) {
466 MessageBeep ( MB_ICONEXCLAMATION );
467 fCtrlBrk = Standard_True;
475 } // end _osd_ctrl_break_handler
477 //============================================================================
479 //============================================================================
481 static LONG __fastcall _osd_raise ( DWORD dwCode, LPTSTR msg )
483 if (msg[0] == TEXT('\x03')) ++msg;
487 case EXCEPTION_ACCESS_VIOLATION:
488 OSD_Exception_ACCESS_VIOLATION::Raise (msg);
490 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
491 OSD_Exception_ARRAY_BOUNDS_EXCEEDED::Raise (msg);
493 case EXCEPTION_DATATYPE_MISALIGNMENT:
494 Standard_ProgramError::Raise (msg);
496 case EXCEPTION_ILLEGAL_INSTRUCTION:
497 OSD_Exception_ILLEGAL_INSTRUCTION::Raise (msg);
499 case EXCEPTION_IN_PAGE_ERROR:
500 OSD_Exception_IN_PAGE_ERROR::Raise (msg);
502 case EXCEPTION_INT_DIVIDE_BY_ZERO:
503 Standard_DivideByZero::Raise (msg);
505 case EXCEPTION_INT_OVERFLOW:
506 OSD_Exception_INT_OVERFLOW::Raise (msg);
508 case EXCEPTION_INVALID_DISPOSITION:
509 OSD_Exception_INVALID_DISPOSITION::Raise (msg);
511 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
512 OSD_Exception_NONCONTINUABLE_EXCEPTION::Raise (msg);
514 case EXCEPTION_PRIV_INSTRUCTION:
515 OSD_Exception_PRIV_INSTRUCTION::Raise (msg);
517 case EXCEPTION_STACK_OVERFLOW:
518 OSD_Exception_STACK_OVERFLOW::Raise (msg);
520 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
521 Standard_DivideByZero::Raise (msg);
523 case EXCEPTION_FLT_STACK_CHECK:
524 case EXCEPTION_FLT_OVERFLOW:
525 Standard_Overflow::Raise (msg);
527 case EXCEPTION_FLT_UNDERFLOW:
528 Standard_Underflow::Raise (msg);
530 case EXCEPTION_FLT_INVALID_OPERATION:
531 case EXCEPTION_FLT_DENORMAL_OPERAND:
532 case EXCEPTION_FLT_INEXACT_RESULT:
533 case STATUS_FLOAT_MULTIPLE_TRAPS:
534 case STATUS_FLOAT_MULTIPLE_FAULTS:
535 Standard_NumericError::Raise (msg);
540 return EXCEPTION_EXECUTE_HANDLER;
543 //============================================================================
545 //============================================================================
547 #if defined(__CYGWIN32__) || defined(__MINGW32__)
550 #define __leave return 0
553 LONG _osd_debug ( void ) {
560 HANDLE hEvent = INVALID_HANDLE_VALUE;
563 TCHAR keyValue[ MAX_PATH ];
564 TCHAR cmdLine[ MAX_PATH ];
565 SECURITY_ATTRIBUTES sa;
566 PROCESS_INFORMATION pi;
573 TEXT( "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug" ),
578 dwValueLen = sizeof ( keyValue );
580 if ( RegQueryValueEx (
581 hKey, TEXT( "Debugger" ), NULL, &dwKeyType, ( unsigned char* )keyValue, &dwValueLen
585 sa.nLength = sizeof ( SECURITY_ATTRIBUTES );
586 sa.lpSecurityDescriptor = NULL;
587 sa.bInheritHandle = TRUE;
589 if ( ( hEvent = CreateEvent ( &sa, TRUE, FALSE, NULL ) ) == NULL ) __leave;
591 wsprintf ( cmdLine, keyValue, GetCurrentProcessId (), hEvent );
593 ZeroMemory ( &si, sizeof ( STARTUPINFO ) );
595 si.cb = sizeof ( STARTUPINFO );
596 si.dwFlags = STARTF_FORCEONFEEDBACK;
598 // cout << "_osd_debug -> CreateProcess" << endl ;
599 if ( !CreateProcess (
600 NULL, cmdLine, NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE,
605 // cout << "_osd_debug -> WaitForSingleObject " << endl ;
606 WaitForSingleObject ( hEvent, INFINITE );
607 // cout << "_osd_debug <- WaitForSingleObject -> CloseHandle " << endl ;
609 CloseHandle ( pi.hProcess );
610 CloseHandle ( pi.hThread );
612 // cout << "_osd_debug fDbgLoaded " << endl ;
619 // cout << "_osd_debug -> CloseHandle(hKey) " << endl ;
620 if ( hKey != INVALID_HANDLE_VALUE ) CloseHandle ( hKey );
621 // cout << "_osd_debug -> CloseHandle(hEvent) " << endl ;
622 if ( hEvent != INVALID_HANDLE_VALUE ) CloseHandle ( hEvent );
623 // cout << "_osd_debug end __finally " << endl ;
629 action = fDbgLoaded ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER;
630 // cout << "_osd_debug return " << action << " EXCEPTION_CONTINUE_EXECUTION("
631 // << EXCEPTION_CONTINUE_EXECUTION << ")" << endl ;
636 #if defined(__CYGWIN32__) || defined(__MINGW32__)
642 // Must be there for compatibility with UNIX system code ----------------------
644 //void OSD::Handler(const OSD_Signals aSig,
645 // const OSD_Signals aCode){}
646 void OSD::Handler(const OSD_Signals theSignal,
647 const Standard_Address theSigInfo,
648 const Standard_Address theContext) {}
650 void OSD::SegvHandler(const OSD_Signals aSig,
651 const Standard_Address code,
652 const Standard_Address scp){}