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