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