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