0025215: Porting to Android - fix minor issues
[occt.git] / src / OSD / OSD_signal.cxx
CommitLineData
973c2be1 1// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 2//
973c2be1 3// This file is part of Open CASCADE Technology software library.
b311480e 4//
d5f74e42 5// This library is free software; you can redistribute it and/or modify it under
6// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 7// by the Free Software Foundation, with special exception defined in the file
8// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9// distribution for complete text of the license and disclaimer of any warranty.
b311480e 10//
973c2be1 11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
7fd59977 13
14#include <OSD.ixx>
15
9bf6baed 16#ifndef _WIN32
7fd59977 17
18//---------- All Systems except Windows NT : ----------------------------------
19
7fd59977 20# include <stdio.h>
21
22#include <OSD_WhoAmI.hxx>
23#include <OSD_SIGHUP.hxx>
24#include <OSD_SIGINT.hxx>
25#include <OSD_SIGQUIT.hxx>
26#include <OSD_SIGILL.hxx>
27#include <OSD_SIGKILL.hxx>
28#include <OSD_SIGBUS.hxx>
29#include <OSD_SIGSEGV.hxx>
30#include <OSD_SIGSYS.hxx>
8a262fa1 31#include <OSD_Exception_CTRL_BREAK.hxx>
7fd59977 32#include <Standard_NumericError.hxx>
7fd59977 33#include <Standard_DivideByZero.hxx>
34#include <Standard_Overflow.hxx>
35
36#include <Standard_ErrorHandler.hxx>
37
38// POSIX threads
03155c18 39#include <pthread.h>
7fd59977 40
41#ifdef linux
42#include <fenv.h>
7fd59977 43static Standard_Boolean fFltExceptions = Standard_False;
44#endif
45
8a262fa1 46// variable signalling that Control-C has been pressed (SIGINT signal)
47static Standard_Boolean fCtrlBrk;
48
7fd59977 49//const OSD_WhoAmI Iam = OSD_WPackage;
50
51typedef void (ACT_SIGIO_HANDLER)(void) ;
52ACT_SIGIO_HANDLER *ADR_ACT_SIGIO_HANDLER = NULL ;
53
7fd59977 54#ifdef DECOSF1
55typedef void (* SIG_PFV) (int);
56#endif
57
7fd59977 58#ifdef __GNUC__
59# include <stdlib.h>
60# include <stdio.h>
61#else
62# ifdef SA_SIGINFO
63# ifndef _AIX
64# include <sys/siginfo.h>
65# endif
66# endif
67#endif
68typedef void (* SIG_PFV) (int);
69
03155c18 70#include <signal.h>
7fd59977 71
9bf6baed 72#if !defined(__ANDROID__)
73 #include <sys/signal.h>
74#endif
75
76#if defined(HAVE_PTHREAD_H) && defined(NO_CXX_EXCEPTION)
7fd59977 77//============================================================================
78//==== GetOldSigAction
79//==== get previous
80//============================================================================
81
82static struct sigaction *GetOldSigAction()
83{
84 static struct sigaction oldSignals[NSIG];
85 return oldSignals;
86}
87
88#ifdef SOLARIS
89static sigfpe_handler_type *GetOldFPE()
90{
91 static sigfpe_handler_type aIEEEHandler[5] = { NULL, NULL, NULL, NULL, NULL } ;
92 return aIEEEHandler;
93}
94#endif
95#endif
96
7fd59977 97//============================================================================
89c4bca8 98//==== Handler
7fd59977 99//==== Catche the differents signals:
100//==== 1- The Fatal signals, which cause the end of process:
101//==== 2- The exceptions which are "signaled" by Raise.
102//==== The Fatal Signals:
103//==== SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGKILL, SIGBUS, SIGSYS
104//==== The Exceptions:
105//==== SIGFPE
106//==== (SUN versions)
107//==== FPE_INTOVF_TRAP // ..... integer overflow
108//==== FPE_INTDIV_TRAP // ..... integer divide by zero
109//==== FPE_FLTINEX_TRAP // ..... [floating inexact result]
110//==== FPE_FLTDIV_TRAP // ..... [floating divide by zero]
111//==== FPE_FLTUND_TRAP // ..... [floating underflow]
112//==== FPE_FLTOPER_TRAP // ..... [floating inexact result]
113//==== FPE_FLTOVF_TRAP // ..... [floating overflow]
114//==== SIGSEGV is handled by "SegvHandler()"
115//============================================================================
7fd59977 116#ifdef SA_SIGINFO
89c4bca8 117static void Handler (const int theSignal, siginfo_t *theSigInfo, const Standard_Address theContext)
118#else
119static void Handler (const int theSignal)
7fd59977 120#endif
7fd59977 121{
122 struct sigaction oldact, act;
7fd59977 123 // re-install the signal
7fd59977 124 if ( ! sigaction (theSignal, NULL, &oldact) ) {
89c4bca8 125 // cout << " signal is " << theSignal << " handler is " << oldact.sa_handler << endl;
126 if (sigaction (theSignal, &oldact, &act)) perror ("sigaction");
127 }
128 else {
129 perror ("sigaction");
7fd59977 130 }
7fd59977 131
132 siginfo_t * aSigInfo = NULL;
133#ifdef SA_SIGINFO
89c4bca8 134 aSigInfo = theSigInfo;
7fd59977 135#endif
136
89c4bca8 137#if defined(HAVE_PTHREAD_H) && defined(NO_CXX_EXCEPTION)
7fd59977 138 if (pthread_self() != getOCCThread() || !Standard_ErrorHandler::IsInTryBlock()) {
139 // use the previous signal handler
89c4bca8 140 // cout << "OSD::Handler: signal " << (int) theSignal << " occured outside a try block " << endl ;
7fd59977 141 struct sigaction *oldSignals = GetOldSigAction();
89c4bca8 142 struct sigaction asigacthandler = oldSignals[theSignal >= 0 && theSignal < NSIG ? theSignal : 0];
143
7fd59977 144 if (asigacthandler.sa_flags & SA_SIGINFO) {
145 void (*aCurInfoHandle)(int, siginfo_t *, void *) = asigacthandler.sa_sigaction;
146 if (aSigInfo) {
89c4bca8 147 switch (aSigInfo->si_signo) {
148 case SIGFPE:
149 {
7fd59977 150#ifdef SOLARIS
89c4bca8 151 sigfpe_handler_type *aIEEEHandlerTab = GetOldFPE();
152 sigfpe_handler_type aIEEEHandler = NULL;
153 switch (aSigInfo->si_code) {
154 case FPE_INTDIV_TRAP :
155 case FPE_FLTDIV_TRAP :
156 aIEEEHandler = aIEEEHandlerTab[1];
157 break;
158 case FPE_INTOVF_TRAP :
159 case FPE_FLTOVF_TRAP :
160 aIEEEHandler = aIEEEHandlerTab[2];
161 break;
162 case FPE_FLTUND_TRAP :
163 aIEEEHandler = aIEEEHandlerTab[4];
164 break;
165 case FPE_FLTRES_TRAP :
166 aIEEEHandler = aIEEEHandlerTab[3];
167 break;
168 case FPE_FLTINV_TRAP :
169 aIEEEHandler = aIEEEHandlerTab[0];
170 break;
171 case FPE_FLTSUB_TRAP :
172 default:
173 break;
174 }
175 if (aIEEEHandler) {
176 // cout << "OSD::Handler: calling previous IEEE signal handler with info" << endl ;
177 (*aIEEEHandler) (theSignal, aSigInfo, theContext);
178 return;
179 }
180#endif
181 break;
182 }
183 default:
184 break;
185 }
7fd59977 186 }
187 if (aCurInfoHandle) {
89c4bca8 188 // cout << "OSD::Handler: calling previous signal handler with info " << aCurInfoHandle << endl ;
189 (*aCurInfoHandle) (theSignal, aSigInfo, theContext);
190 cerr << " previous signal handler return" << endl ;
191 return;
7fd59977 192 }
193 else {
194 // cout << "OSD::Handler: no handler with info for the signal" << endl;
195 }
89c4bca8 196 }
197 else {
198 // no siginfo needed for the signal
7fd59977 199 void (*aCurHandler) (int) = asigacthandler.sa_handler;
200 if(aCurHandler) {
89c4bca8 201 // cout << "OSD::Handler: calling previous signal handler" << endl ;
202 (*aCurHandler) (theSignal);
203 cerr << " previous signal handler return" << endl ;
204 return;
205 }
7fd59977 206 }
207 // cout << " Signal occured outside a try block, but no handler for it" <<endl;
208 return;
209 }
210#endif
211
7fd59977 212 // cout << "OSD::Handler: signal " << (int) theSignal << " occured inside a try block " << endl ;
89c4bca8 213 if ( ADR_ACT_SIGIO_HANDLER != NULL )
214 (*ADR_ACT_SIGIO_HANDLER)() ;
7fd59977 215#ifdef linux
216 if (fFltExceptions)
217 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
218 //feenableexcept (FE_INVALID | FE_DIVBYZERO);
219#endif
7fd59977 220 sigset_t set;
221 sigemptyset(&set);
89c4bca8 222 switch (theSignal) {
7fd59977 223 case SIGHUP:
224 OSD_SIGHUP::NewInstance("SIGHUP 'hangup' detected.")->Jump();
225 exit(SIGHUP);
226 break;
7fd59977 227 case SIGINT:
8a262fa1 228 // For safe handling of Control-C as stop event, arm a variable but do not
229 // generate longjump (we are out of context anyway)
230 fCtrlBrk = Standard_True;
89c4bca8 231 // OSD_SIGINT::NewInstance("SIGINT 'interrupt' detected.")->Jump();
232 // exit(SIGINT);
7fd59977 233 break;
7fd59977 234 case SIGQUIT:
235 OSD_SIGQUIT::NewInstance("SIGQUIT 'quit' detected.")->Jump();
236 exit(SIGQUIT);
237 break;
7fd59977 238 case SIGILL:
239 OSD_SIGILL::NewInstance("SIGILL 'illegal instruction' detected.")->Jump();
240 exit(SIGILL);
241 break;
7fd59977 242 case SIGKILL:
243 OSD_SIGKILL::NewInstance("SIGKILL 'kill' detected.")->Jump();
244 exit(SIGKILL);
245 break;
7fd59977 246 case SIGBUS:
247 sigaddset(&set, SIGBUS);
248 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
249 OSD_SIGBUS::NewInstance("SIGBUS 'bus error' detected.")->Jump();
250 exit(SIGBUS);
251 break;
7fd59977 252 case SIGSEGV:
253 OSD_SIGSEGV::NewInstance("SIGSEGV 'segmentation violation' detected.")->Jump();
254 exit(SIGSEGV);
255 break;
7fd59977 256#ifdef SIGSYS
257 case SIGSYS:
258 OSD_SIGSYS::NewInstance("SIGSYS 'bad argument to system call' detected.")->Jump();
259 exit(SIGSYS);
260 break;
261#endif
89c4bca8 262 case SIGFPE:
7fd59977 263 sigaddset(&set, SIGFPE);
264 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
265#ifdef DECOSF1
89c4bca8 266 // Pour DEC/OSF1 SIGFPE = Division par zero.
267 // should be clarified why in debug mode only?
7fd59977 268#ifdef DEBUG
269 Standard_DivideByZero::NewInstance('')->Jump;
270#endif
271 break;
89c4bca8 272#endif
7fd59977 273#if (!defined (__sun)) && (!defined(SOLARIS))
274 Standard_NumericError::NewInstance("SIGFPE Arithmetic exception detected")->Jump();
275 break;
276#else
277 // Reste SOLARIS
89c4bca8 278 if (aSigInfo) {
7fd59977 279 switch(aSigInfo->si_code) {
280 case FPE_FLTDIV_TRAP :
89c4bca8 281 Standard_DivideByZero::NewInstance("Floating Divide By Zero")->Jump();
282 break;
7fd59977 283 case FPE_INTDIV_TRAP :
89c4bca8 284 Standard_DivideByZero::NewInstance("Integer Divide By Zero")->Jump();
285 break;
7fd59977 286 case FPE_FLTOVF_TRAP :
89c4bca8 287 Standard_Overflow::NewInstance("Floating Overflow")->Jump();
288 break;
7fd59977 289 case FPE_INTOVF_TRAP :
89c4bca8 290 Standard_Overflow::NewInstance("Integer Overflow")->Jump();
291 break;
7fd59977 292 case FPE_FLTUND_TRAP :
89c4bca8 293 Standard_NumericError::NewInstance("Floating Underflow")->Jump();
294 break;
7fd59977 295 case FPE_FLTRES_TRAP:
89c4bca8 296 Standard_NumericError::NewInstance("Floating Point Inexact Result")->Jump();
297 break;
7fd59977 298 case FPE_FLTINV_TRAP :
89c4bca8 299 Standard_NumericError::NewInstance("Invalid Floating Point Operation")->Jump();
300 break;
7fd59977 301 default:
89c4bca8 302 Standard_NumericError::NewInstance("Numeric Error")->Jump();
303 break;
7fd59977 304 }
89c4bca8 305 } else {
7fd59977 306 Standard_NumericError::NewInstance("SIGFPE Arithmetic exception detected")->Jump();
307 }
308#endif
309 break;
7fd59977 310#if defined (__sgi) || defined(IRIX)
89c4bca8 311 case SIGTRAP:
7fd59977 312 sigaddset(&set, SIGTRAP);
313 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
314 Standard_DivideByZero::NewInstance("SIGTRAP IntegerDivideByZero")->Jump(); break;
315#endif
316 default:
89c4bca8 317 cout << "Unexpected signal " << theSignal << endl ;
318 break;
8a262fa1 319 }
320}
321
7fd59977 322//============================================================================
89c4bca8 323//==== SegvHandler
7fd59977 324//============================================================================
7fd59977 325#ifdef SA_SIGINFO
326
89c4bca8 327static void SegvHandler(const int theSignal,
328 siginfo_t *ip,
329 const Standard_Address theContext)
7fd59977 330{
89c4bca8 331#ifdef NO_CXX_EXCEPTION
7fd59977 332 if (!Standard_ErrorHandler::IsInTryBlock()) {
89c4bca8 333 Handler(theSignal, ip, theContext);
7fd59977 334 return;
335 }
7fd59977 336#endif
7fd59977 337#ifdef linux
338 if (fFltExceptions)
339 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
340 //feenableexcept (FE_INVALID | FE_DIVBYZERO);
341#endif
7fd59977 342// cout << "OSD::SegvHandler activated(SA_SIGINFO)" << endl ;
343 if ( ip != NULL ) {
344 sigset_t set;
345 sigemptyset(&set);
346 sigaddset(&set, SIGSEGV);
347 sigprocmask (SIG_UNBLOCK, &set, NULL) ;
89c4bca8 348 void *address = ip->si_addr ;
4d9421a9 349 {
7fd59977 350 char Msg[100];
351 sprintf(Msg,"SIGSEGV 'segmentation violation' detected. Address %lx",
89c4bca8 352 (long ) address ) ;
7fd59977 353 OSD_SIGSEGV::NewInstance(Msg)->Jump();
354 }
89c4bca8 355 }
356 else {
7fd59977 357 cout << "Wrong undefined address." << endl ;
89c4bca8 358 }
7fd59977 359 exit(SIGSEGV);
360}
361
89c4bca8 362#elif defined (_hpux) || defined(HPUX)
7fd59977 363// Not ACTIVE ? SA_SIGINFO is defined on SUN, OSF, SGI and HP (and Linux) !
364// pour version 09.07
89c4bca8 365
366static void SegvHandler(const int theSignal,
367 siginfo_t *ip,
368 const Standard_Address theContext)
7fd59977 369{
370 unsigned long Space ;
371 unsigned long Offset ;
372 char Msg[100] ;
373
89c4bca8 374 if ( theContext != NULL ) {
375 Space = ((struct sigcontext *)theContext)->sc_sl.sl_ss.ss_cr20 ;
376 Offset = ((struct sigcontext *)theContext)->sc_sl.sl_ss.ss_cr21 ;
7fd59977 377// cout << "Wrong address = " << hex(Offset) << endl ;
4d9421a9 378 {
89c4bca8 379 sprintf(Msg,"SIGSEGV 'segmentation violation' detected. Address %lx",Offset) ;
380 OSD_SIGSEGV::Jump(Msg);
7fd59977 381// scp->sc_pcoq_head = scp->sc_pcoq_tail ; Permettrait de continuer a
382// scp->sc_pcoq_tail = scp->sc_pcoq_tail + 0x4 ; l'intruction suivant le segv.
383 }
384 }
89c4bca8 385 else {
7fd59977 386 cout << "Wrong undefined address." << endl ;
89c4bca8 387 }
7fd59977 388 exit(SIGSEGV);
89c4bca8 389}
390
391#endif
392
393//============================================================================
394//==== SetSignal
395//==== Set the differents signals:
396//============================================================================
397
398void OSD::SetSignal(const Standard_Boolean aFloatingSignal)
399{
400 static int first_time = 3 ;
401 struct sigaction act, oact;
402 int stat = 0;
403
404 if( aFloatingSignal ) {
405 //==== Enable the floating point exceptions ===============
406#if defined (__sun) || defined (SOLARIS)
407 sigfpe_handler_type PHandler = (sigfpe_handler_type) Handler ;
408 stat = ieee_handler("set", "invalid", PHandler);
409 stat = ieee_handler("set", "division", PHandler) || stat;
410 stat = ieee_handler("set", "overflow", PHandler) || stat;
411
412 //stat = ieee_handler("set", "underflow", PHandler) || stat;
413 //stat = ieee_handler("set", "inexact", PHandler) || stat;
414
415 if (stat) {
416 cerr << "ieee_handler does not work !!! KO " << endl;
417 }
418#elif defined (linux)
419 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
420 //feenableexcept (FE_INVALID | FE_DIVBYZERO);
421 fFltExceptions = Standard_True;
422#endif
423 }
424 else if ( first_time & 1 ) {
425// cout << "SetSignal( Standard_False ) is not implemented..." << endl ;
426 first_time = first_time & (~ 1) ;
427 }
428
429#if defined (sgi) || defined (IRIX )
430 if ( first_time & 2 ) {
431 char *TRAP_FPE = getenv("TRAP_FPE") ;
432 if ( TRAP_FPE == NULL ) {
433 cout << "On SGI you must set TRAP_FPE environment variable : " << endl ;
434 cout << "set env(TRAP_FPE) \"UNDERFL=FLUSH_ZERO;OVERFL=DEFAULT;DIVZERO=DEFAULT;INT_OVERFL=DEFAULT\" or" << endl ;
435 cout << "setenv TRAP_FPE \"UNDERFL=FLUSH_ZERO;OVERFL=DEFAULT;DIVZERO=DEFAULT;INT_OVERFL=DEFAULT\"" << endl ;
436// exit(1) ;
437 first_time = first_time & (~ 2) ;
438 }
439 }
440#endif
441
442 //==== Save the old Signal Handler, and set the new one ===================
443
444 sigemptyset(&act.sa_mask) ;
445
446#ifdef SA_RESTART
447 act.sa_flags = SA_RESTART ;
448#else
449 act.sa_flags = 0 ;
450#endif
451#ifdef SA_SIGINFO
452 act.sa_flags = act.sa_flags | SA_SIGINFO ;
453 act.sa_sigaction = /*(void(*)(int, siginfo_t *, void*))*/ Handler;
454#else
455 act.sa_handler = /*(SIG_PFV)*/ Handler;
456#endif
7fd59977 457
89c4bca8 458 //==== Always detected the signal "SIGFPE" =================================
459 stat = sigaction(SIGFPE,&act,&oact); // ...... floating point exception
460 if (stat) {
461 cerr << "sigaction does not work !!! KO " << endl;
462 perror("sigaction ");
463 }
464
465 //==== Detected the only the "free" signals ================================
466 sigaction(SIGHUP,&act,&oact); // ...... hangup
467
468#ifdef OBJS
469 if(oact.sa_handler)
470 sigaction(SIGHUP,&oact,&oact);
471#endif
472
473 sigaction(SIGINT,&act,&oact); // ...... interrupt
474
475#ifdef OBJS
476 if(oact.sa_handler)
477 sigaction(SIGINT,&oact,&oact);
7fd59977 478#endif
89c4bca8 479
480 sigaction(SIGQUIT,&act,&oact); // ...... quit
481
482#ifdef OBJS
483 if(oact.sa_handler)
484 sigaction(SIGQUIT,&oact,&oact);
485#endif
486
487 sigaction(SIGILL,&act,&oact); // ...... illegal instruction
488
489#ifdef OBJS
490 if(oact.sa_handler)
491 sigaction(SIGILL,&oact,&oact);
492#endif
493
494 sigaction(SIGBUS,&act,&oact); // ...... bus error
495
496#ifdef OBJS
497 if(oact.sa_handler)
498 sigaction(SIGBUS,&oact,&oact);
499#endif
500
501#if (!defined (linux)) && (!defined(LININTEL))
502 sigaction(SIGSYS,&act,&oact); // ...... bad argument to system call
503
504# ifdef OBJS
505 if(oact.sa_handler)
506 sigaction(SIGSYS,&oact,&oact);
507# endif
508#endif
509
510#if defined (__sgi) || defined(IRIX)
511 sigaction(SIGTRAP,&act,&oact); // Integer Divide By Zero (IRIX)
512
513# ifdef OBJS
514 if(oact.sa_handler)
515 sigaction(SIGTRAP,&oact,&oact);
516# endif
517#endif
518
519#ifdef SA_SIGINFO
520 act.sa_sigaction = /*(void(*)(int, siginfo_t *, void*))*/ SegvHandler;
7fd59977 521#else
89c4bca8 522 act.sa_handler = /*(SIG_PFV)*/ SegvHandler;
523#endif
7fd59977 524
89c4bca8 525 if ( sigaction( SIGSEGV , &act , &oact ) ) // ...... segmentation violation
526 perror("OSD::SetSignal sigaction( SIGSEGV , &act , &oact ) ") ;
7fd59977 527
89c4bca8 528#ifdef OBJS
529 if(oact.sa_handler)
530 sigaction(SIGSEGV,&oact,&oact);
531#endif
532#if defined(__osf__) || defined(DECOSF1)
533 struct sigaction action, prev_action;
534 action.sa_handler = SIG_IGN;
535 action.sa_mask = 0;
536 action.sa_flags = 0;
537
538 if (sigaction (SIGFPE, &action, &prev_action) == -1) {
539 perror ("sigaction");
540 exit (1);
541 }
7fd59977 542#endif
89c4bca8 543
544}
545
546//============================================================================
547//==== ControlBreak
548//============================================================================
549
550void OSD :: ControlBreak ()
551{
552 if ( fCtrlBrk ) {
553 fCtrlBrk = Standard_False;
554 OSD_Exception_CTRL_BREAK::Raise ("*** INTERRUPT ***");
555 }
556}
557
7fd59977 558#endif