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