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