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