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