0029152: Coding Rules - eliminate GCC compiler warnings -Wmisleading-indentation...
[occt.git] / src / OSD / OSD_signal.cxx
CommitLineData
973c2be1 1// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 2//
973c2be1 3// This file is part of Open CASCADE Technology software library.
b311480e 4//
d5f74e42 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
973c2be1 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.
b311480e 10//
973c2be1 11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
7fd59977 13
42cf5bc1 14
15#include <OSD.hxx>
536a3cb8 16#include <OSD_Exception_CTRL_BREAK.hxx>
17#include <Standard_DivideByZero.hxx>
18#include <Standard_Overflow.hxx>
19
20#ifdef _WIN32
21//---------------------------- Windows NT System --------------------------------
22
536a3cb8 23#ifdef NOUSER
24#undef NOUSER
25#endif
742cc8b0 26#ifdef NONLS
27#undef NONLS
28#endif
536a3cb8 29#include <windows.h>
30
742cc8b0 31#include <Strsafe.h>
32
536a3cb8 33#ifndef STATUS_FLOAT_MULTIPLE_FAULTS
34 // <ntstatus.h>
35 #define STATUS_FLOAT_MULTIPLE_FAULTS (0xC00002B4L)
36 #define STATUS_FLOAT_MULTIPLE_TRAPS (0xC00002B5L)
37#endif
38
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>
50
51#include <OSD_Environment.hxx>
52#include <Standard_Underflow.hxx>
53#include <Standard_ProgramError.hxx>
54#include <Standard_Mutex.hxx>
55
56#include <OSD_WNT_1.hxx>
57
58#ifdef _MSC_VER
59#include <eh.h>
60#include <malloc.h>
61#endif
62
63#include <process.h>
64#include <signal.h>
65#include <float.h>
66
94afca11 67static Standard_Boolean fCtrlBrk;
68#if !defined(__CYGWIN32__) && !defined(__MINGW32__)
536a3cb8 69static Standard_Boolean fMsgBox;
70static Standard_Boolean fFltExceptions;
71static Standard_Boolean fDbgLoaded;
536a3cb8 72
73// used to forbid simultaneous execution of setting / executing handlers
74static Standard_Mutex THE_SIGNAL_MUTEX;
75
76static LONG __fastcall _osd_raise ( DWORD, LPSTR );
77static BOOL WINAPI _osd_ctrl_break_handler ( DWORD );
78
742cc8b0 79#ifndef OCCT_UWP
536a3cb8 80static LONG _osd_debug ( void );
742cc8b0 81#endif
536a3cb8 82
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 )
85
86//=======================================================================
87//function : CallHandler
88//purpose :
89//=======================================================================
90static LONG CallHandler (DWORD dwExceptionCode,
91 ptrdiff_t ExceptionInformation1,
92 ptrdiff_t ExceptionInformation0)
93{
536a3cb8 94 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
742cc8b0 95
96 static wchar_t buffer[2048];
97
536a3cb8 98 int flterr = 0;
99
100 buffer[0] = '\0' ;
101
102// cout << "CallHandler " << dwExceptionCode << endl ;
103 switch ( dwExceptionCode ) {
104 case EXCEPTION_FLT_DENORMAL_OPERAND:
105// cout << "CallHandler : EXCEPTION_FLT_DENORMAL_OPERAND:" << endl ;
742cc8b0 106 StringCchCopyW (buffer, _countof(buffer), L"FLT DENORMAL OPERAND");
536a3cb8 107 flterr = 1 ;
108 break ;
109 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
110// cout << "CallHandler : EXCEPTION_FLT_DIVIDE_BY_ZERO:" << endl ;
742cc8b0 111 StringCchCopyW (buffer, _countof(buffer), L"FLT DIVIDE BY ZERO");
536a3cb8 112 flterr = 1 ;
113 break ;
114 case EXCEPTION_FLT_INEXACT_RESULT:
115// cout << "CallHandler : EXCEPTION_FLT_INEXACT_RESULT:" << endl ;
742cc8b0 116 StringCchCopyW (buffer, _countof(buffer), L"FLT INEXACT RESULT");
536a3cb8 117 flterr = 1 ;
118 break ;
119 case EXCEPTION_FLT_INVALID_OPERATION:
120// cout << "CallHandler : EXCEPTION_FLT_INVALID_OPERATION:" << endl ;
742cc8b0 121 StringCchCopyW (buffer, _countof(buffer), L"FLT INVALID OPERATION");
536a3cb8 122 flterr = 1 ;
123 break ;
124 case EXCEPTION_FLT_OVERFLOW:
125// cout << "CallHandler : EXCEPTION_FLT_OVERFLOW:" << endl ;
742cc8b0 126 StringCchCopyW (buffer, _countof(buffer), L"FLT OVERFLOW");
536a3cb8 127 flterr = 1 ;
128 break ;
129 case EXCEPTION_FLT_STACK_CHECK:
130// cout << "CallHandler : EXCEPTION_FLT_STACK_CHECK:" << endl ;
742cc8b0 131 StringCchCopyW (buffer, _countof(buffer), L"FLT STACK CHECK");
536a3cb8 132 flterr = 1 ;
133 break ;
134 case EXCEPTION_FLT_UNDERFLOW:
135// cout << "CallHandler : EXCEPTION_FLT_UNDERFLOW:" << endl ;
742cc8b0 136 StringCchCopyW (buffer, _countof(buffer), L"FLT UNDERFLOW");
536a3cb8 137 flterr = 1 ;
138 break ;
139 case STATUS_FLOAT_MULTIPLE_TRAPS:
140// cout << "CallHandler : EXCEPTION_FLT_UNDERFLOW:" << endl ;
742cc8b0 141 StringCchCopyW (buffer, _countof(buffer), L"FLT MULTIPLE TRAPS (possible overflow in conversion of double to integer)");
536a3cb8 142 flterr = 1 ;
143 break ;
144 case STATUS_FLOAT_MULTIPLE_FAULTS:
145// cout << "CallHandler : EXCEPTION_FLT_UNDERFLOW:" << endl ;
742cc8b0 146 StringCchCopyW (buffer, _countof(buffer), L"FLT MULTIPLE FAULTS");
536a3cb8 147 flterr = 1 ;
148 break ;
149 case STATUS_NO_MEMORY:
150// cout << "CallHandler : STATUS_NO_MEMORY:" << endl ;
9775fa61 151 throw OSD_Exception_STATUS_NO_MEMORY ( "MEMORY ALLOCATION ERROR ( no room in the process heap )" );
536a3cb8 152 case EXCEPTION_ACCESS_VIOLATION:
153// cout << "CallHandler : EXCEPTION_ACCESS_VIOLATION:" << endl ;
742cc8b0 154 StringCchPrintfW (buffer, _countof(buffer), L"%s%s%s0x%.8p%s%s%s", L"ACCESS VIOLATION",
155 fMsgBox ? L"\n" : L" ", L"at address ",
536a3cb8 156 ExceptionInformation1 ,
742cc8b0 157 L" during '",
158 ExceptionInformation0 ? L"WRITE" : L"READ",
159 L"' operation");
536a3cb8 160 break;
161 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
162// cout << "CallHandler : EXCEPTION_ARRAY_BOUNDS_EXCEEDED:" << endl ;
742cc8b0 163 StringCchCopyW (buffer, _countof(buffer), L"ARRAY BOUNDS EXCEEDED");
536a3cb8 164 break;
165 case EXCEPTION_DATATYPE_MISALIGNMENT:
166// cout << "CallHandler : EXCEPTION_DATATYPE_MISALIGNMENT:" << endl ;
742cc8b0 167 StringCchCopyW (buffer, _countof(buffer), L"DATATYPE MISALIGNMENT");
536a3cb8 168 break;
169
170 case EXCEPTION_ILLEGAL_INSTRUCTION:
171// cout << "CallHandler : EXCEPTION_ILLEGAL_INSTRUCTION:" << endl ;
742cc8b0 172 StringCchCopyW (buffer, _countof(buffer), L"ILLEGAL INSTRUCTION");
536a3cb8 173 break;
174
175 case EXCEPTION_IN_PAGE_ERROR:
176// cout << "CallHandler : EXCEPTION_IN_PAGE_ERROR:" << endl ;
742cc8b0 177 StringCchCopyW (buffer, _countof(buffer), L"IN_PAGE ERROR");
536a3cb8 178 break;
179
180 case EXCEPTION_INT_DIVIDE_BY_ZERO:
181// cout << "CallHandler : EXCEPTION_INT_DIVIDE_BY_ZERO:" << endl ;
742cc8b0 182 StringCchCopyW (buffer, _countof(buffer), L"INTEGER DIVISION BY ZERO");
536a3cb8 183 break;
184
185 case EXCEPTION_INT_OVERFLOW:
186// cout << "CallHandler : EXCEPTION_INT_OVERFLOW:" << endl ;
742cc8b0 187 StringCchCopyW (buffer, _countof(buffer), L"INTEGER OVERFLOW");
536a3cb8 188 break;
189
190 case EXCEPTION_INVALID_DISPOSITION:
191// cout << "CallHandler : EXCEPTION_INVALID_DISPOSITION:" << endl ;
742cc8b0 192 StringCchCopyW (buffer, _countof(buffer), L"INVALID DISPOSITION");
536a3cb8 193 break;
194
195 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
196// cout << "CallHandler : EXCEPTION_NONCONTINUABLE_EXCEPTION:" << endl ;
742cc8b0 197 StringCchCopyW (buffer, _countof(buffer), L"NONCONTINUABLE EXCEPTION");
536a3cb8 198 break;
199
200 case EXCEPTION_PRIV_INSTRUCTION:
201// cout << "CallHandler : EXCEPTION_PRIV_INSTRUCTION:" << endl ;
742cc8b0 202 StringCchCopyW (buffer, _countof(buffer), L"PRIVELEGED INSTRUCTION ENCOUNTERED");
536a3cb8 203 break;
204
205 case EXCEPTION_STACK_OVERFLOW:
206// cout << "CallHandler : EXCEPTION_STACK_OVERFLOW:" << endl ;
742cc8b0 207#if defined( _MSC_VER ) && ( _MSC_VER >= 1300 ) && !defined(OCCT_UWP)
536a3cb8 208 // try recovering from stack overflow: available in MS VC++ 7.0
209 if (!_resetstkoflw())
742cc8b0 210 StringCchCopyW (buffer, _countof(buffer), L"Unrecoverable STACK OVERFLOW");
536a3cb8 211 else
212#endif
742cc8b0 213 StringCchCopyW (buffer, _countof(buffer), L"STACK OVERFLOW");
536a3cb8 214 break;
215
216 default:
742cc8b0 217 StringCchPrintfW (buffer, _countof(buffer), L"unknown exception code 0x%x, params 0x%p 0x%p",
536a3cb8 218 dwExceptionCode, ExceptionInformation1, ExceptionInformation0 );
219
220 } // end switch
221
222 // provide message to the user with possibility to stop
742cc8b0 223 size_t idx;
224 StringCchLengthW (buffer, _countof(buffer),&idx);
536a3cb8 225 if ( idx && fMsgBox && dwExceptionCode != EXCEPTION_NONCONTINUABLE_EXCEPTION ) {
226 // reset FP operations before message box, otherwise it may fail to show up
227 _fpreset();
228 _clearfp();
229
742cc8b0 230#ifndef OCCT_UWP
536a3cb8 231 MessageBeep ( MB_ICONHAND );
742cc8b0 232 int aChoice = ::MessageBoxW (0, buffer, L"OCCT Exception Handler", MB_ABORTRETRYIGNORE | MB_ICONSTOP);
536a3cb8 233 if (aChoice == IDRETRY)
234 {
235 _osd_debug();
236 DebugBreak();
237 } else if (aChoice == IDABORT)
238 exit(0xFFFF);
742cc8b0 239#endif
536a3cb8 240 }
241
242 // reset FPE state
243 if ( flterr ) {
244 if ( !fFltExceptions ) return EXCEPTION_EXECUTE_HANDLER;
245 _fpreset () ;
246 _clearfp() ;
247 _controlfp ( 0, _OSD_FPX ) ; // JR add :
248// cout << "OSD::WntHandler _controlfp( 0, _OSD_FPX ) " << hex << _controlfp(0,0) << dec << endl ;
249 }
742cc8b0 250
251 char aBufferA[2048];
252 WideCharToMultiByte(CP_UTF8, 0, buffer, -1, aBufferA, sizeof(aBufferA), NULL, NULL);
253 return _osd_raise(dwExceptionCode, aBufferA);
536a3cb8 254}
255
256//=======================================================================
257//function : SIGWntHandler
258//purpose : Will only be used if user calls ::raise() function with
259// signal type set in OSD::SetSignal() - SIGSEGV, SIGFPE, SIGILL
260// (the latter will likely be removed in the future)
261//=======================================================================
262static void SIGWntHandler (int signum, int sub_code)
263{
536a3cb8 264 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
265 switch( signum ) {
266 case SIGFPE :
267 if ( signal( signum , (void(*)(int))SIGWntHandler ) == SIG_ERR )
268 cout << "signal error" << endl ;
269 switch( sub_code ) {
270 case _FPE_INVALID :
271 CallHandler( EXCEPTION_FLT_INVALID_OPERATION ,0,0) ;
272 break ;
273 case _FPE_DENORMAL :
274 CallHandler( EXCEPTION_FLT_DENORMAL_OPERAND ,0,0) ;
275 break ;
276 case _FPE_ZERODIVIDE :
277 CallHandler( EXCEPTION_FLT_DIVIDE_BY_ZERO ,0,0) ;
278 break ;
279 case _FPE_OVERFLOW :
280 CallHandler( EXCEPTION_FLT_OVERFLOW ,0,0) ;
281 break ;
282 case _FPE_UNDERFLOW :
283 CallHandler( EXCEPTION_FLT_UNDERFLOW ,0,0) ;
284 break ;
285 case _FPE_INEXACT :
286 CallHandler( EXCEPTION_FLT_INEXACT_RESULT ,0,0) ;
287 break ;
288 default:
9775fa61 289 cout << "SIGWntHandler(default) -> throw Standard_NumericError(\"Floating Point Error\");" << endl;
290 throw Standard_NumericError("Floating Point Error");
536a3cb8 291 break ;
292 }
293 break ;
294 case SIGSEGV :
295 if ( signal( signum, (void(*)(int))SIGWntHandler ) == SIG_ERR )
296 cout << "signal error" << endl ;
297 CallHandler( EXCEPTION_ACCESS_VIOLATION ,0,0) ;
298 break ;
299 case SIGILL :
300 if ( signal( signum, (void(*)(int))SIGWntHandler ) == SIG_ERR )
301 cout << "signal error" << endl ;
302 CallHandler( EXCEPTION_ILLEGAL_INSTRUCTION ,0,0) ;
303 break ;
304 default:
305 cout << "SIGWntHandler unexpected signal : " << signum << endl ;
306 break ;
307 }
742cc8b0 308#ifndef OCCT_UWP
536a3cb8 309 DebugBreak ();
742cc8b0 310#endif
536a3cb8 311}
94afca11 312#endif
536a3cb8 313
314//=======================================================================
315//function : TranslateSE
316//purpose : Translate Structural Exceptions into C++ exceptions
317// Will be used when user's code is compiled with /EHa option
318//=======================================================================
319#ifdef _MSC_VER
320// If this file compiled with the default MSVC options for exception
321// handling (/GX or /EHsc) then the following warning is issued:
322// warning C4535: calling _set_se_translator() requires /EHa
323// However it is correctly inserted and used when user's code compiled with /EHa.
324// So, here we disable the warning.
325#pragma warning (disable:4535)
326
327static void TranslateSE( unsigned int theCode, EXCEPTION_POINTERS* theExcPtr )
328{
329 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
330 ptrdiff_t info1 = 0, info0 = 0;
331 if ( theExcPtr ) {
332 info1 = theExcPtr->ExceptionRecord->ExceptionInformation[1];
333 info0 = theExcPtr->ExceptionRecord->ExceptionInformation[0];
334 }
335 CallHandler(theCode, info1, info0);
336}
337#endif
338
339//=======================================================================
340//function : WntHandler
341//purpose : Will be used when user's code is compiled with /EHs
342// option and unless user sets his own exception handler with
343// ::SetUnhandledExceptionFilter().
344//=======================================================================
94afca11 345#if !defined(__CYGWIN32__) && !defined(__MINGW32__)
536a3cb8 346static LONG WINAPI WntHandler (EXCEPTION_POINTERS *lpXP)
347{
348 DWORD dwExceptionCode = lpXP->ExceptionRecord->ExceptionCode;
349
350 return CallHandler (dwExceptionCode,
351 lpXP->ExceptionRecord->ExceptionInformation[1],
352 lpXP->ExceptionRecord->ExceptionInformation[0]);
353}
94afca11 354#endif
536a3cb8 355
356//=======================================================================
357//function : SetSignal
358//purpose :
359//=======================================================================
360void OSD::SetSignal (const Standard_Boolean theFloatingSignal)
361{
362#if !defined(__CYGWIN32__) && !defined(__MINGW32__)
363 Standard_Mutex::Sentry aSentry (THE_SIGNAL_MUTEX); // lock the mutex to prevent simultaneous handling
1ce0716b 364#if !defined(OCCT_UWP) || defined(NTDDI_WIN10_TH2)
536a3cb8 365 LPTOP_LEVEL_EXCEPTION_FILTER aPreviousFilter;
366
742cc8b0 367 OSD_Environment env ("CSF_DEBUG_MODE");
536a3cb8 368 TCollection_AsciiString val = env.Value();
369 if (!env.Failed())
370 {
371 cout << "Environment variable CSF_DEBUG_MODE setted.\n";
372 fMsgBox = Standard_True;
373 }
374 else
375 {
376 fMsgBox = Standard_False;
377 }
378
379 // Set exception handler (ignored when running under debugger). It will be used in most cases
380 // when user's code is compiled with /EHs
381 // Replaces the existing top-level exception filter for all existing and all future threads
382 // in the calling process
383 aPreviousFilter = ::SetUnhandledExceptionFilter (/*(LPTOP_LEVEL_EXCEPTION_FILTER)*/ WntHandler);
1ce0716b 384#endif // NTDDI_WIN10_TH2
7fd59977 385
536a3cb8 386 // Signal handlers will only be used when the method ::raise() will be used
387 // Handlers must be set for every thread
388 if (signal (SIGSEGV, (void(*)(int))SIGWntHandler) == SIG_ERR)
389 cout << "signal(OSD::SetSignal) error\n";
390 if (signal (SIGFPE, (void(*)(int))SIGWntHandler) == SIG_ERR)
391 cout << "signal(OSD::SetSignal) error\n";
392 if (signal (SIGILL, (void(*)(int))SIGWntHandler) == SIG_ERR)
393 cout << "signal(OSD::SetSignal) error\n";
394
395 // Set Ctrl-C and Ctrl-Break handler
396 fCtrlBrk = Standard_False;
742cc8b0 397#ifndef OCCT_UWP
536a3cb8 398 SetConsoleCtrlHandler (&_osd_ctrl_break_handler, TRUE);
742cc8b0 399#endif
536a3cb8 400#ifdef _MSC_VER
401// _se_translator_function pOldSeFunc =
402 _set_se_translator (TranslateSE);
403#endif
404
405 fFltExceptions = theFloatingSignal;
406 if (theFloatingSignal)
407 {
408 _controlfp (0, _OSD_FPX); // JR add :
409 }
410 else {
411 _controlfp (_OSD_FPX, _OSD_FPX); // JR add :
412 }
cda06ac0 413#else
414 (void)theFloatingSignal; // silence compiler warning on MinGw
536a3cb8 415#endif
416} // end OSD :: SetSignal
417
418//============================================================================
419//==== ControlBreak
420//============================================================================
421void OSD::ControlBreak () {
422 if ( fCtrlBrk ) {
423 fCtrlBrk = Standard_False;
9775fa61 424 throw OSD_Exception_CTRL_BREAK ( "*** INTERRUPT ***" );
536a3cb8 425 }
426} // end OSD :: ControlBreak
94afca11 427#if !defined(__MINGW32__) && !defined(__CYGWIN32__)
742cc8b0 428#ifndef OCCT_UWP
536a3cb8 429//============================================================================
430//==== _osd_ctrl_break_handler
431//============================================================================
432static 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;
436 } else
437 exit ( 254 );
438
439 return TRUE;
440} // end _osd_ctrl_break_handler
742cc8b0 441#endif
536a3cb8 442//============================================================================
443//==== _osd_raise
444//============================================================================
445static LONG __fastcall _osd_raise ( DWORD dwCode, LPSTR msg )
446{
447 if (msg[0] == '\x03') ++msg;
448
449 switch (dwCode)
450 {
451 case EXCEPTION_ACCESS_VIOLATION:
9775fa61 452 throw OSD_Exception_ACCESS_VIOLATION(msg);
536a3cb8 453 break;
454 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
9775fa61 455 throw OSD_Exception_ARRAY_BOUNDS_EXCEEDED(msg);
536a3cb8 456 break;
457 case EXCEPTION_DATATYPE_MISALIGNMENT:
9775fa61 458 throw Standard_ProgramError(msg);
536a3cb8 459 break;
460 case EXCEPTION_ILLEGAL_INSTRUCTION:
9775fa61 461 throw OSD_Exception_ILLEGAL_INSTRUCTION(msg);
536a3cb8 462 break;
463 case EXCEPTION_IN_PAGE_ERROR:
9775fa61 464 throw OSD_Exception_IN_PAGE_ERROR(msg);
536a3cb8 465 break;
466 case EXCEPTION_INT_DIVIDE_BY_ZERO:
9775fa61 467 throw Standard_DivideByZero(msg);
536a3cb8 468 break;
469 case EXCEPTION_INT_OVERFLOW:
9775fa61 470 throw OSD_Exception_INT_OVERFLOW(msg);
536a3cb8 471 break;
472 case EXCEPTION_INVALID_DISPOSITION:
9775fa61 473 throw OSD_Exception_INVALID_DISPOSITION(msg);
536a3cb8 474 break;
475 case EXCEPTION_NONCONTINUABLE_EXCEPTION:
9775fa61 476 throw OSD_Exception_NONCONTINUABLE_EXCEPTION(msg);
536a3cb8 477 break;
478 case EXCEPTION_PRIV_INSTRUCTION:
9775fa61 479 throw OSD_Exception_PRIV_INSTRUCTION(msg);
536a3cb8 480 break;
481 case EXCEPTION_STACK_OVERFLOW:
9775fa61 482 throw OSD_Exception_STACK_OVERFLOW(msg);
536a3cb8 483 break;
484 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
9775fa61 485 throw Standard_DivideByZero(msg);
536a3cb8 486 break;
487 case EXCEPTION_FLT_STACK_CHECK:
488 case EXCEPTION_FLT_OVERFLOW:
9775fa61 489 throw Standard_Overflow(msg);
536a3cb8 490 break;
491 case EXCEPTION_FLT_UNDERFLOW:
9775fa61 492 throw Standard_Underflow(msg);
536a3cb8 493 break;
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:
9775fa61 499 throw Standard_NumericError(msg);
536a3cb8 500 break;
501 default:
502 break;
503 } // end switch
504 return EXCEPTION_EXECUTE_HANDLER;
505} // end _osd_raise
506
507//============================================================================
508//==== _osd_debug
509//============================================================================
742cc8b0 510#ifndef OCCT_UWP
536a3cb8 511LONG _osd_debug ( void ) {
512
513 LONG action ;
514
515 if ( !fDbgLoaded ) {
516
517 HKEY hKey = NULL;
518 HANDLE hEvent = INVALID_HANDLE_VALUE;
519 DWORD dwKeyType;
520 DWORD dwValueLen;
521 TCHAR keyValue[ MAX_PATH ];
522 TCHAR cmdLine[ MAX_PATH ];
523 SECURITY_ATTRIBUTES sa;
524 PROCESS_INFORMATION pi;
525 STARTUPINFO si;
526
527 __try {
528
529 if ( RegOpenKey (
530 HKEY_LOCAL_MACHINE,
531 TEXT( "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug" ),
532 &hKey
533 ) != ERROR_SUCCESS
534 ) __leave;
535
536 dwValueLen = sizeof ( keyValue );
537
538 if ( RegQueryValueEx (
539 hKey, TEXT( "Debugger" ), NULL, &dwKeyType, ( unsigned char* )keyValue, &dwValueLen
540 ) != ERROR_SUCCESS
541 ) __leave;
542
543 sa.nLength = sizeof ( SECURITY_ATTRIBUTES );
544 sa.lpSecurityDescriptor = NULL;
545 sa.bInheritHandle = TRUE;
546
547 if ( ( hEvent = CreateEvent ( &sa, TRUE, FALSE, NULL ) ) == NULL ) __leave;
548
742cc8b0 549 StringCchPrintf(cmdLine, _countof(cmdLine), keyValue, GetCurrentProcessId(), hEvent);
536a3cb8 550
551 ZeroMemory ( &si, sizeof ( STARTUPINFO ) );
552
553 si.cb = sizeof ( STARTUPINFO );
554 si.dwFlags = STARTF_FORCEONFEEDBACK;
555
556 // cout << "_osd_debug -> CreateProcess" << endl ;
557 if ( !CreateProcess (
558 NULL, cmdLine, NULL, NULL, TRUE, CREATE_DEFAULT_ERROR_MODE,
559 NULL, NULL, &si, &pi
560 )
561 ) __leave;
562
563 // cout << "_osd_debug -> WaitForSingleObject " << endl ;
564 WaitForSingleObject ( hEvent, INFINITE );
565 // cout << "_osd_debug <- WaitForSingleObject -> CloseHandle " << endl ;
566
567 CloseHandle ( pi.hProcess );
568 CloseHandle ( pi.hThread );
569
570 // cout << "_osd_debug fDbgLoaded " << endl ;
571 fDbgLoaded = TRUE;
572
573 } // end __try
574
575 __finally {
576
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 ;
582
583 } // end __finally
584
585 } /* end if */
586
587 action = fDbgLoaded ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER;
588// cout << "_osd_debug return " << action << " EXCEPTION_CONTINUE_EXECUTION("
589// << EXCEPTION_CONTINUE_EXECUTION << ")" << endl ;
590 return action ;
591
592} // end _osd_debug
536a3cb8 593
742cc8b0 594#endif
595#endif
536a3cb8 596#else
7fd59977 597
598//---------- All Systems except Windows NT : ----------------------------------
599
7fd59977 600# include <stdio.h>
601
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>
7fd59977 612
613#include <Standard_ErrorHandler.hxx>
614
615// POSIX threads
03155c18 616#include <pthread.h>
7fd59977 617
c381fda2 618#ifdef __linux__
896faa72 619#include <cfenv>
620//#include <fenv.h>
7fd59977 621static Standard_Boolean fFltExceptions = Standard_False;
622#endif
623
8a262fa1 624// variable signalling that Control-C has been pressed (SIGINT signal)
625static Standard_Boolean fCtrlBrk;
626
7fd59977 627//const OSD_WhoAmI Iam = OSD_WPackage;
628
629typedef void (ACT_SIGIO_HANDLER)(void) ;
630ACT_SIGIO_HANDLER *ADR_ACT_SIGIO_HANDLER = NULL ;
631
7fd59977 632#ifdef DECOSF1
633typedef void (* SIG_PFV) (int);
634#endif
635
7fd59977 636#ifdef __GNUC__
637# include <stdlib.h>
638# include <stdio.h>
639#else
cda06ac0 640# ifdef SA_SIGINFO
7fd59977 641# ifndef _AIX
642# include <sys/siginfo.h>
643# endif
644# endif
645#endif
646typedef void (* SIG_PFV) (int);
647
03155c18 648#include <signal.h>
7fd59977 649
d8d01f6e 650#if !defined(__ANDROID__) && !defined(__QNX__)
9bf6baed 651 #include <sys/signal.h>
652#endif
653
7fd59977 654//============================================================================
89c4bca8 655//==== Handler
7fd59977 656//==== Catche the differents signals:
657//==== 1- The Fatal signals, which cause the end of process:
658//==== 2- The exceptions which are "signaled" by Raise.
659//==== The Fatal Signals:
660//==== SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGKILL, SIGBUS, SIGSYS
661//==== The Exceptions:
662//==== SIGFPE
663//==== (SUN versions)
664//==== FPE_INTOVF_TRAP // ..... integer overflow
665//==== FPE_INTDIV_TRAP // ..... integer divide by zero
666//==== FPE_FLTINEX_TRAP // ..... [floating inexact result]
667//==== FPE_FLTDIV_TRAP // ..... [floating divide by zero]
668//==== FPE_FLTUND_TRAP // ..... [floating underflow]
669//==== FPE_FLTOPER_TRAP // ..... [floating inexact result]
670//==== FPE_FLTOVF_TRAP // ..... [floating overflow]
671//==== SIGSEGV is handled by "SegvHandler()"
672//============================================================================
7fd59977 673#ifdef SA_SIGINFO
c85385c0 674static void Handler (const int theSignal, siginfo_t */*theSigInfo*/, const Standard_Address /*theContext*/)
89c4bca8 675#else
676static void Handler (const int theSignal)
7fd59977 677#endif
7fd59977 678{
679 struct sigaction oldact, act;
7fd59977 680 // re-install the signal
7fd59977 681 if ( ! sigaction (theSignal, NULL, &oldact) ) {
89c4bca8 682 // cout << " signal is " << theSignal << " handler is " << oldact.sa_handler << endl;
683 if (sigaction (theSignal, &oldact, &act)) perror ("sigaction");
684 }
685 else {
686 perror ("sigaction");
7fd59977 687 }
7fd59977 688
7fd59977 689 // cout << "OSD::Handler: signal " << (int) theSignal << " occured inside a try block " << endl ;
89c4bca8 690 if ( ADR_ACT_SIGIO_HANDLER != NULL )
691 (*ADR_ACT_SIGIO_HANDLER)() ;
c381fda2 692#ifdef __linux__
7fd59977 693 if (fFltExceptions)
694 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
695 //feenableexcept (FE_INVALID | FE_DIVBYZERO);
696#endif
7fd59977 697 sigset_t set;
698 sigemptyset(&set);
89c4bca8 699 switch (theSignal) {
7fd59977 700 case SIGHUP:
701 OSD_SIGHUP::NewInstance("SIGHUP 'hangup' detected.")->Jump();
702 exit(SIGHUP);
703 break;
7fd59977 704 case SIGINT:
8a262fa1 705 // For safe handling of Control-C as stop event, arm a variable but do not
706 // generate longjump (we are out of context anyway)
707 fCtrlBrk = Standard_True;
89c4bca8 708 // OSD_SIGINT::NewInstance("SIGINT 'interrupt' detected.")->Jump();
709 // exit(SIGINT);
7fd59977 710 break;
7fd59977 711 case SIGQUIT:
712 OSD_SIGQUIT::NewInstance("SIGQUIT 'quit' detected.")->Jump();
713 exit(SIGQUIT);
714 break;
7fd59977 715 case SIGILL:
716 OSD_SIGILL::NewInstance("SIGILL 'illegal instruction' detected.")->Jump();
717 exit(SIGILL);
718 break;
7fd59977 719 case SIGKILL:
720 OSD_SIGKILL::NewInstance("SIGKILL 'kill' detected.")->Jump();
721 exit(SIGKILL);
722 break;
7fd59977 723 case SIGBUS:
724 sigaddset(&set, SIGBUS);
725 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
726 OSD_SIGBUS::NewInstance("SIGBUS 'bus error' detected.")->Jump();
727 exit(SIGBUS);
728 break;
7fd59977 729 case SIGSEGV:
730 OSD_SIGSEGV::NewInstance("SIGSEGV 'segmentation violation' detected.")->Jump();
731 exit(SIGSEGV);
732 break;
7fd59977 733#ifdef SIGSYS
734 case SIGSYS:
735 OSD_SIGSYS::NewInstance("SIGSYS 'bad argument to system call' detected.")->Jump();
736 exit(SIGSYS);
737 break;
738#endif
89c4bca8 739 case SIGFPE:
7fd59977 740 sigaddset(&set, SIGFPE);
741 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
742#ifdef DECOSF1
89c4bca8 743 // Pour DEC/OSF1 SIGFPE = Division par zero.
7fd59977 744 Standard_DivideByZero::NewInstance('')->Jump;
7fd59977 745 break;
89c4bca8 746#endif
7fd59977 747#if (!defined (__sun)) && (!defined(SOLARIS))
748 Standard_NumericError::NewInstance("SIGFPE Arithmetic exception detected")->Jump();
749 break;
750#else
751 // Reste SOLARIS
89c4bca8 752 if (aSigInfo) {
7fd59977 753 switch(aSigInfo->si_code) {
754 case FPE_FLTDIV_TRAP :
89c4bca8 755 Standard_DivideByZero::NewInstance("Floating Divide By Zero")->Jump();
756 break;
7fd59977 757 case FPE_INTDIV_TRAP :
89c4bca8 758 Standard_DivideByZero::NewInstance("Integer Divide By Zero")->Jump();
759 break;
7fd59977 760 case FPE_FLTOVF_TRAP :
89c4bca8 761 Standard_Overflow::NewInstance("Floating Overflow")->Jump();
762 break;
7fd59977 763 case FPE_INTOVF_TRAP :
89c4bca8 764 Standard_Overflow::NewInstance("Integer Overflow")->Jump();
765 break;
7fd59977 766 case FPE_FLTUND_TRAP :
89c4bca8 767 Standard_NumericError::NewInstance("Floating Underflow")->Jump();
768 break;
7fd59977 769 case FPE_FLTRES_TRAP:
89c4bca8 770 Standard_NumericError::NewInstance("Floating Point Inexact Result")->Jump();
771 break;
7fd59977 772 case FPE_FLTINV_TRAP :
89c4bca8 773 Standard_NumericError::NewInstance("Invalid Floating Point Operation")->Jump();
774 break;
7fd59977 775 default:
89c4bca8 776 Standard_NumericError::NewInstance("Numeric Error")->Jump();
777 break;
7fd59977 778 }
89c4bca8 779 } else {
7fd59977 780 Standard_NumericError::NewInstance("SIGFPE Arithmetic exception detected")->Jump();
781 }
782#endif
783 break;
7fd59977 784#if defined (__sgi) || defined(IRIX)
89c4bca8 785 case SIGTRAP:
7fd59977 786 sigaddset(&set, SIGTRAP);
787 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
788 Standard_DivideByZero::NewInstance("SIGTRAP IntegerDivideByZero")->Jump(); break;
789#endif
790 default:
0797d9d3 791#ifdef OCCT_DEBUG
89c4bca8 792 cout << "Unexpected signal " << theSignal << endl ;
63c629aa 793#endif
89c4bca8 794 break;
8a262fa1 795 }
796}
797
7fd59977 798//============================================================================
89c4bca8 799//==== SegvHandler
7fd59977 800//============================================================================
7fd59977 801#ifdef SA_SIGINFO
802
89c4bca8 803static void SegvHandler(const int theSignal,
804 siginfo_t *ip,
805 const Standard_Address theContext)
7fd59977 806{
04e93070 807 (void)theSignal; // silence GCC warnings
808 (void)theContext;
9775fa61 809
c381fda2 810#ifdef __linux__
7fd59977 811 if (fFltExceptions)
812 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
813 //feenableexcept (FE_INVALID | FE_DIVBYZERO);
814#endif
7fd59977 815// cout << "OSD::SegvHandler activated(SA_SIGINFO)" << endl ;
816 if ( ip != NULL ) {
817 sigset_t set;
818 sigemptyset(&set);
819 sigaddset(&set, SIGSEGV);
820 sigprocmask (SIG_UNBLOCK, &set, NULL) ;
89c4bca8 821 void *address = ip->si_addr ;
4d9421a9 822 {
7fd59977 823 char Msg[100];
824 sprintf(Msg,"SIGSEGV 'segmentation violation' detected. Address %lx",
89c4bca8 825 (long ) address ) ;
7fd59977 826 OSD_SIGSEGV::NewInstance(Msg)->Jump();
827 }
89c4bca8 828 }
0797d9d3 829#ifdef OCCT_DEBUG
89c4bca8 830 else {
7fd59977 831 cout << "Wrong undefined address." << endl ;
89c4bca8 832 }
63c629aa 833#endif
7fd59977 834 exit(SIGSEGV);
835}
836
89c4bca8 837#elif defined (_hpux) || defined(HPUX)
7fd59977 838// Not ACTIVE ? SA_SIGINFO is defined on SUN, OSF, SGI and HP (and Linux) !
839// pour version 09.07
89c4bca8 840
841static void SegvHandler(const int theSignal,
842 siginfo_t *ip,
843 const Standard_Address theContext)
7fd59977 844{
845 unsigned long Space ;
846 unsigned long Offset ;
847 char Msg[100] ;
848
89c4bca8 849 if ( theContext != NULL ) {
850 Space = ((struct sigcontext *)theContext)->sc_sl.sl_ss.ss_cr20 ;
851 Offset = ((struct sigcontext *)theContext)->sc_sl.sl_ss.ss_cr21 ;
7fd59977 852// cout << "Wrong address = " << hex(Offset) << endl ;
4d9421a9 853 {
89c4bca8 854 sprintf(Msg,"SIGSEGV 'segmentation violation' detected. Address %lx",Offset) ;
855 OSD_SIGSEGV::Jump(Msg);
7fd59977 856// scp->sc_pcoq_head = scp->sc_pcoq_tail ; Permettrait de continuer a
857// scp->sc_pcoq_tail = scp->sc_pcoq_tail + 0x4 ; l'intruction suivant le segv.
858 }
859 }
0797d9d3 860#ifdef OCCT_DEBUG
89c4bca8 861 else {
7fd59977 862 cout << "Wrong undefined address." << endl ;
89c4bca8 863 }
63c629aa 864#endif
7fd59977 865 exit(SIGSEGV);
89c4bca8 866}
867
868#endif
869
870//============================================================================
cda06ac0 871//==== SetSignal
89c4bca8 872//==== Set the differents signals:
873//============================================================================
874
cda06ac0 875void OSD::SetSignal(const Standard_Boolean aFloatingSignal)
89c4bca8 876{
89c4bca8 877 struct sigaction act, oact;
878 int stat = 0;
879
880 if( aFloatingSignal ) {
881 //==== Enable the floating point exceptions ===============
882#if defined (__sun) || defined (SOLARIS)
883 sigfpe_handler_type PHandler = (sigfpe_handler_type) Handler ;
884 stat = ieee_handler("set", "invalid", PHandler);
885 stat = ieee_handler("set", "division", PHandler) || stat;
886 stat = ieee_handler("set", "overflow", PHandler) || stat;
887
888 //stat = ieee_handler("set", "underflow", PHandler) || stat;
889 //stat = ieee_handler("set", "inexact", PHandler) || stat;
890
891 if (stat) {
0797d9d3 892#ifdef OCCT_DEBUG
89c4bca8 893 cerr << "ieee_handler does not work !!! KO " << endl;
63c629aa 894#endif
89c4bca8 895 }
c381fda2 896#elif defined (__linux__)
89c4bca8 897 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
89c4bca8 898 fFltExceptions = Standard_True;
899#endif
900 }
66cfcd0f 901 else
902 {
903#if defined (__linux__)
904 fedisableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
905 fFltExceptions = Standard_False;
906#endif
89c4bca8 907 }
908
909#if defined (sgi) || defined (IRIX )
66cfcd0f 910 char *TRAP_FPE = getenv("TRAP_FPE") ;
911 if ( TRAP_FPE == NULL ) {
0797d9d3 912#ifdef OCCT_DEBUG
66cfcd0f 913 cout << "On SGI you must set TRAP_FPE environment variable : " << endl ;
914 cout << "set env(TRAP_FPE) \"UNDERFL=FLUSH_ZERO;OVERFL=DEFAULT;DIVZERO=DEFAULT;INT_OVERFL=DEFAULT\" or" << endl ;
915 cout << "setenv TRAP_FPE \"UNDERFL=FLUSH_ZERO;OVERFL=DEFAULT;DIVZERO=DEFAULT;INT_OVERFL=DEFAULT\"" << endl ;
63c629aa 916#endif
89c4bca8 917 }
918#endif
919
920 //==== Save the old Signal Handler, and set the new one ===================
921
922 sigemptyset(&act.sa_mask) ;
923
924#ifdef SA_RESTART
925 act.sa_flags = SA_RESTART ;
926#else
927 act.sa_flags = 0 ;
928#endif
929#ifdef SA_SIGINFO
930 act.sa_flags = act.sa_flags | SA_SIGINFO ;
931 act.sa_sigaction = /*(void(*)(int, siginfo_t *, void*))*/ Handler;
932#else
933 act.sa_handler = /*(SIG_PFV)*/ Handler;
934#endif
7fd59977 935
89c4bca8 936 //==== Always detected the signal "SIGFPE" =================================
cda06ac0 937 stat = sigaction(SIGFPE,&act,&oact); // ...... floating point exception
89c4bca8 938 if (stat) {
0797d9d3 939#ifdef OCCT_DEBUG
89c4bca8 940 cerr << "sigaction does not work !!! KO " << endl;
63c629aa 941#endif
89c4bca8 942 perror("sigaction ");
943 }
944
945 //==== Detected the only the "free" signals ================================
cda06ac0 946 sigaction(SIGHUP,&act,&oact); // ...... hangup
89c4bca8 947
948#ifdef OBJS
cda06ac0 949 if(oact.sa_handler)
89c4bca8 950 sigaction(SIGHUP,&oact,&oact);
951#endif
952
cda06ac0 953 sigaction(SIGINT,&act,&oact); // ...... interrupt
89c4bca8 954
955#ifdef OBJS
cda06ac0 956 if(oact.sa_handler)
89c4bca8 957 sigaction(SIGINT,&oact,&oact);
7fd59977 958#endif
cda06ac0 959
89c4bca8 960 sigaction(SIGQUIT,&act,&oact); // ...... quit
961
962#ifdef OBJS
cda06ac0 963 if(oact.sa_handler)
89c4bca8 964 sigaction(SIGQUIT,&oact,&oact);
965#endif
966
cda06ac0 967 sigaction(SIGILL,&act,&oact); // ...... illegal instruction
89c4bca8 968
969#ifdef OBJS
cda06ac0 970 if(oact.sa_handler)
89c4bca8 971 sigaction(SIGILL,&oact,&oact);
972#endif
973
cda06ac0 974 sigaction(SIGBUS,&act,&oact); // ...... bus error
89c4bca8 975
976#ifdef OBJS
cda06ac0 977 if(oact.sa_handler)
89c4bca8 978 sigaction(SIGBUS,&oact,&oact);
979#endif
980
c381fda2 981#if !defined(__linux__)
89c4bca8 982 sigaction(SIGSYS,&act,&oact); // ...... bad argument to system call
983
984# ifdef OBJS
cda06ac0 985 if(oact.sa_handler)
89c4bca8 986 sigaction(SIGSYS,&oact,&oact);
987# endif
988#endif
989
990#if defined (__sgi) || defined(IRIX)
991 sigaction(SIGTRAP,&act,&oact); // Integer Divide By Zero (IRIX)
992
993# ifdef OBJS
cda06ac0 994 if(oact.sa_handler)
89c4bca8 995 sigaction(SIGTRAP,&oact,&oact);
996# endif
997#endif
998
999#ifdef SA_SIGINFO
1000 act.sa_sigaction = /*(void(*)(int, siginfo_t *, void*))*/ SegvHandler;
7fd59977 1001#else
89c4bca8 1002 act.sa_handler = /*(SIG_PFV)*/ SegvHandler;
1003#endif
7fd59977 1004
89c4bca8 1005 if ( sigaction( SIGSEGV , &act , &oact ) ) // ...... segmentation violation
1006 perror("OSD::SetSignal sigaction( SIGSEGV , &act , &oact ) ") ;
7fd59977 1007
89c4bca8 1008#ifdef OBJS
cda06ac0 1009 if(oact.sa_handler)
89c4bca8 1010 sigaction(SIGSEGV,&oact,&oact);
1011#endif
1012#if defined(__osf__) || defined(DECOSF1)
1013 struct sigaction action, prev_action;
1014 action.sa_handler = SIG_IGN;
1015 action.sa_mask = 0;
1016 action.sa_flags = 0;
cda06ac0 1017
89c4bca8 1018 if (sigaction (SIGFPE, &action, &prev_action) == -1) {
1019 perror ("sigaction");
1020 exit (1);
1021 }
7fd59977 1022#endif
89c4bca8 1023
1024}
1025
1026//============================================================================
cda06ac0 1027//==== ControlBreak
89c4bca8 1028//============================================================================
1029
cda06ac0 1030void OSD :: ControlBreak ()
89c4bca8 1031{
1032 if ( fCtrlBrk ) {
1033 fCtrlBrk = Standard_False;
9775fa61 1034 throw OSD_Exception_CTRL_BREAK("*** INTERRUPT ***");
89c4bca8 1035 }
1036}
1037
7fd59977 1038#endif