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