1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
5 // This library is free software; you can redistribute it and / or modify it
6 // under the terms of the GNU Lesser General Public version 2.1 as published
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.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
18 //---------- All Systems except Windows NT : ----------------------------------
26 #include <OSD_WhoAmI.hxx>
27 #include <OSD_SIGHUP.hxx>
28 #include <OSD_SIGINT.hxx>
29 #include <OSD_SIGQUIT.hxx>
30 #include <OSD_SIGILL.hxx>
31 #include <OSD_SIGKILL.hxx>
32 #include <OSD_SIGBUS.hxx>
33 #include <OSD_SIGSEGV.hxx>
34 #include <OSD_SIGSYS.hxx>
35 #include <OSD_Exception_CTRL_BREAK.hxx>
36 #include <Standard_NumericError.hxx>
37 #include <Standard_NullObject.hxx>
38 #include <Standard_DivideByZero.hxx>
39 #include <Standard_Overflow.hxx>
41 #include <Standard_ErrorHandler.hxx>
49 static pthread_t getOCCThread () {
50 static pthread_t TheOCCThread = 0;
57 #include <fpu_control.h>
58 static Standard_Boolean fFltExceptions = Standard_False;
61 // variable signalling that Control-C has been pressed (SIGINT signal)
62 static Standard_Boolean fCtrlBrk;
64 //const OSD_WhoAmI Iam = OSD_WPackage;
66 typedef void (ACT_SIGIO_HANDLER)(void) ;
67 ACT_SIGIO_HANDLER *ADR_ACT_SIGIO_HANDLER = NULL ;
69 #if defined(HAVE_FLOATINGPOINT_H) && defined(HAVE_SYS_MACHSIG_H)
70 # include <floatingpoint.h>
71 # include <sys/machsig.h>
72 // JPT : Difference between SUN/SUNOS and SUN/SOLARIS
73 # define FPE_FLTDIV_TRAP FPE_FLTDIV
74 # define FPE_INTDIV_TRAP FPE_INTDIV
75 # define FPE_FLTOVF_TRAP FPE_FLTOVF
76 # define FPE_INTOVF_TRAP FPE_INTOVF
77 # define FPE_FLTUND_TRAP FPE_FLTUND
79 #define FPE_FLTRES_TRAP FPE_FLTRES /* floating point inexact result */
80 #define FPE_FLTINV_TRAP FPE_FLTINV /* invalid floating point operation */
81 #define FPE_FLTSUB_TRAP FPE_FLTSUB /* subscript out of range */
83 extern "C" {int ieee_handler(char *,char *, sigfpe_handler_type&);}
88 typedef void (* SIG_PFV) (int);
91 #if defined(HAVE_SIGFPE_H) && defined(HAVE_SYS_SIGINFO_H)
93 # include <sys/siginfo.h>
94 # define FPE_FLTDIV_TRAP FPE_FLTDIV
95 # define FPE_INTDIV_TRAP FPE_INTDIV
96 # define FPE_FLTOVF_TRAP FPE_FLTOVF
97 # define FPE_INTOVF_TRAP FPE_INTOVF
98 # define FPE_FLTUND_TRAP FPE_FLTUND
107 # include <sys/siginfo.h>
111 typedef void (* SIG_PFV) (int);
117 #ifdef HAVE_SYS_SIGNAL_H
118 # include <sys/signal.h>
121 #if defined(HAVE_PTHREAD_H) && defined(NO_CXX_EXCEPTION)
122 //============================================================================
123 //==== GetOldSigAction
125 //============================================================================
127 static struct sigaction *GetOldSigAction()
129 static struct sigaction oldSignals[NSIG];
134 static sigfpe_handler_type *GetOldFPE()
136 static sigfpe_handler_type aIEEEHandler[5] = { NULL, NULL, NULL, NULL, NULL } ;
142 //============================================================================
144 //==== Catche the differents signals:
145 //==== 1- The Fatal signals, which cause the end of process:
146 //==== 2- The exceptions which are "signaled" by Raise.
147 //==== The Fatal Signals:
148 //==== SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGKILL, SIGBUS, SIGSYS
149 //==== The Exceptions:
151 //==== (SUN versions)
152 //==== FPE_INTOVF_TRAP // ..... integer overflow
153 //==== FPE_INTDIV_TRAP // ..... integer divide by zero
154 //==== FPE_FLTINEX_TRAP // ..... [floating inexact result]
155 //==== FPE_FLTDIV_TRAP // ..... [floating divide by zero]
156 //==== FPE_FLTUND_TRAP // ..... [floating underflow]
157 //==== FPE_FLTOPER_TRAP // ..... [floating inexact result]
158 //==== FPE_FLTOVF_TRAP // ..... [floating overflow]
159 //==== SIGSEGV is handled by "SegvHandler()"
160 //============================================================================
162 static void Handler (const int theSignal, siginfo_t *theSigInfo, const Standard_Address theContext)
164 static void Handler (const int theSignal)
167 struct sigaction oldact, act;
168 // re-install the signal
169 if ( ! sigaction (theSignal, NULL, &oldact) ) {
170 // cout << " signal is " << theSignal << " handler is " << oldact.sa_handler << endl;
171 if (sigaction (theSignal, &oldact, &act)) perror ("sigaction");
174 perror ("sigaction");
177 siginfo_t * aSigInfo = NULL;
179 aSigInfo = theSigInfo;
182 #if defined(HAVE_PTHREAD_H) && defined(NO_CXX_EXCEPTION)
183 if (pthread_self() != getOCCThread() || !Standard_ErrorHandler::IsInTryBlock()) {
184 // use the previous signal handler
185 // cout << "OSD::Handler: signal " << (int) theSignal << " occured outside a try block " << endl ;
186 struct sigaction *oldSignals = GetOldSigAction();
187 struct sigaction asigacthandler = oldSignals[theSignal >= 0 && theSignal < NSIG ? theSignal : 0];
189 if (asigacthandler.sa_flags & SA_SIGINFO) {
190 void (*aCurInfoHandle)(int, siginfo_t *, void *) = asigacthandler.sa_sigaction;
192 switch (aSigInfo->si_signo) {
196 sigfpe_handler_type *aIEEEHandlerTab = GetOldFPE();
197 sigfpe_handler_type aIEEEHandler = NULL;
198 switch (aSigInfo->si_code) {
199 case FPE_INTDIV_TRAP :
200 case FPE_FLTDIV_TRAP :
201 aIEEEHandler = aIEEEHandlerTab[1];
203 case FPE_INTOVF_TRAP :
204 case FPE_FLTOVF_TRAP :
205 aIEEEHandler = aIEEEHandlerTab[2];
207 case FPE_FLTUND_TRAP :
208 aIEEEHandler = aIEEEHandlerTab[4];
210 case FPE_FLTRES_TRAP :
211 aIEEEHandler = aIEEEHandlerTab[3];
213 case FPE_FLTINV_TRAP :
214 aIEEEHandler = aIEEEHandlerTab[0];
216 case FPE_FLTSUB_TRAP :
221 // cout << "OSD::Handler: calling previous IEEE signal handler with info" << endl ;
222 (*aIEEEHandler) (theSignal, aSigInfo, theContext);
232 if (aCurInfoHandle) {
233 // cout << "OSD::Handler: calling previous signal handler with info " << aCurInfoHandle << endl ;
234 (*aCurInfoHandle) (theSignal, aSigInfo, theContext);
235 cerr << " previous signal handler return" << endl ;
239 // cout << "OSD::Handler: no handler with info for the signal" << endl;
243 // no siginfo needed for the signal
244 void (*aCurHandler) (int) = asigacthandler.sa_handler;
246 // cout << "OSD::Handler: calling previous signal handler" << endl ;
247 (*aCurHandler) (theSignal);
248 cerr << " previous signal handler return" << endl ;
252 // cout << " Signal occured outside a try block, but no handler for it" <<endl;
257 // cout << "OSD::Handler: signal " << (int) theSignal << " occured inside a try block " << endl ;
258 if ( ADR_ACT_SIGIO_HANDLER != NULL )
259 (*ADR_ACT_SIGIO_HANDLER)() ;
262 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
263 //feenableexcept (FE_INVALID | FE_DIVBYZERO);
269 OSD_SIGHUP::NewInstance("SIGHUP 'hangup' detected.")->Jump();
273 // For safe handling of Control-C as stop event, arm a variable but do not
274 // generate longjump (we are out of context anyway)
275 fCtrlBrk = Standard_True;
276 // OSD_SIGINT::NewInstance("SIGINT 'interrupt' detected.")->Jump();
280 OSD_SIGQUIT::NewInstance("SIGQUIT 'quit' detected.")->Jump();
284 OSD_SIGILL::NewInstance("SIGILL 'illegal instruction' detected.")->Jump();
288 OSD_SIGKILL::NewInstance("SIGKILL 'kill' detected.")->Jump();
292 sigaddset(&set, SIGBUS);
293 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
294 OSD_SIGBUS::NewInstance("SIGBUS 'bus error' detected.")->Jump();
298 OSD_SIGSEGV::NewInstance("SIGSEGV 'segmentation violation' detected.")->Jump();
303 OSD_SIGSYS::NewInstance("SIGSYS 'bad argument to system call' detected.")->Jump();
308 sigaddset(&set, SIGFPE);
309 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
311 // Pour DEC/OSF1 SIGFPE = Division par zero.
312 // should be clarified why in debug mode only?
314 Standard_DivideByZero::NewInstance('')->Jump;
318 #if (!defined (__sun)) && (!defined(SOLARIS))
319 Standard_NumericError::NewInstance("SIGFPE Arithmetic exception detected")->Jump();
324 switch(aSigInfo->si_code) {
325 case FPE_FLTDIV_TRAP :
326 Standard_DivideByZero::NewInstance("Floating Divide By Zero")->Jump();
328 case FPE_INTDIV_TRAP :
329 Standard_DivideByZero::NewInstance("Integer Divide By Zero")->Jump();
331 case FPE_FLTOVF_TRAP :
332 Standard_Overflow::NewInstance("Floating Overflow")->Jump();
334 case FPE_INTOVF_TRAP :
335 Standard_Overflow::NewInstance("Integer Overflow")->Jump();
337 case FPE_FLTUND_TRAP :
338 Standard_NumericError::NewInstance("Floating Underflow")->Jump();
340 case FPE_FLTRES_TRAP:
341 Standard_NumericError::NewInstance("Floating Point Inexact Result")->Jump();
343 case FPE_FLTINV_TRAP :
344 Standard_NumericError::NewInstance("Invalid Floating Point Operation")->Jump();
347 Standard_NumericError::NewInstance("Numeric Error")->Jump();
351 Standard_NumericError::NewInstance("SIGFPE Arithmetic exception detected")->Jump();
355 #if defined (__sgi) || defined(IRIX)
357 sigaddset(&set, SIGTRAP);
358 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
359 Standard_DivideByZero::NewInstance("SIGTRAP IntegerDivideByZero")->Jump(); break;
362 cout << "Unexpected signal " << theSignal << endl ;
367 //============================================================================
369 //============================================================================
372 static void SegvHandler(const int theSignal,
374 const Standard_Address theContext)
376 #ifdef NO_CXX_EXCEPTION
377 if (!Standard_ErrorHandler::IsInTryBlock()) {
378 Handler(theSignal, ip, theContext);
384 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
385 //feenableexcept (FE_INVALID | FE_DIVBYZERO);
387 // cout << "OSD::SegvHandler activated(SA_SIGINFO)" << endl ;
391 sigaddset(&set, SIGSEGV);
392 sigprocmask (SIG_UNBLOCK, &set, NULL) ;
393 void *address = ip->si_addr ;
394 if ( (((long) address )& ~0xffff) == (long) UndefinedHandleAddress ) {
395 Standard_NullObject::NewInstance("Attempt to access to null object")->Jump();
399 sprintf(Msg,"SIGSEGV 'segmentation violation' detected. Address %lx",
401 OSD_SIGSEGV::NewInstance(Msg)->Jump();
405 cout << "Wrong undefined address." << endl ;
410 #elif defined (_hpux) || defined(HPUX)
411 // Not ACTIVE ? SA_SIGINFO is defined on SUN, OSF, SGI and HP (and Linux) !
412 // pour version 09.07
414 static void SegvHandler(const int theSignal,
416 const Standard_Address theContext)
418 unsigned long Space ;
419 unsigned long Offset ;
422 if ( theContext != NULL ) {
423 Space = ((struct sigcontext *)theContext)->sc_sl.sl_ss.ss_cr20 ;
424 Offset = ((struct sigcontext *)theContext)->sc_sl.sl_ss.ss_cr21 ;
425 // cout << "Wrong address = " << hex(Offset) << endl ;
426 if ((Offset & ~0xffff) == (long)UndefinedHandleAddress) {
427 Standard_NullObject::Jump("Attempt to access to null object") ;
430 sprintf(Msg,"SIGSEGV 'segmentation violation' detected. Address %lx",Offset) ;
431 OSD_SIGSEGV::Jump(Msg);
432 // scp->sc_pcoq_head = scp->sc_pcoq_tail ; Permettrait de continuer a
433 // scp->sc_pcoq_tail = scp->sc_pcoq_tail + 0x4 ; l'intruction suivant le segv.
437 cout << "Wrong undefined address." << endl ;
444 //============================================================================
446 //==== Set the differents signals:
447 //============================================================================
449 void OSD::SetSignal(const Standard_Boolean aFloatingSignal)
451 static int first_time = 3 ;
452 struct sigaction act, oact;
455 if( aFloatingSignal ) {
456 //==== Enable the floating point exceptions ===============
457 #if defined (__sun) || defined (SOLARIS)
458 sigfpe_handler_type PHandler = (sigfpe_handler_type) Handler ;
459 stat = ieee_handler("set", "invalid", PHandler);
460 stat = ieee_handler("set", "division", PHandler) || stat;
461 stat = ieee_handler("set", "overflow", PHandler) || stat;
463 //stat = ieee_handler("set", "underflow", PHandler) || stat;
464 //stat = ieee_handler("set", "inexact", PHandler) || stat;
467 cerr << "ieee_handler does not work !!! KO " << endl;
469 #elif defined (linux)
470 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
471 //feenableexcept (FE_INVALID | FE_DIVBYZERO);
472 fFltExceptions = Standard_True;
475 else if ( first_time & 1 ) {
476 // cout << "SetSignal( Standard_False ) is not implemented..." << endl ;
477 first_time = first_time & (~ 1) ;
480 #if defined (sgi) || defined (IRIX )
481 if ( first_time & 2 ) {
482 char *TRAP_FPE = getenv("TRAP_FPE") ;
483 if ( TRAP_FPE == NULL ) {
484 cout << "On SGI you must set TRAP_FPE environment variable : " << endl ;
485 cout << "set env(TRAP_FPE) \"UNDERFL=FLUSH_ZERO;OVERFL=DEFAULT;DIVZERO=DEFAULT;INT_OVERFL=DEFAULT\" or" << endl ;
486 cout << "setenv TRAP_FPE \"UNDERFL=FLUSH_ZERO;OVERFL=DEFAULT;DIVZERO=DEFAULT;INT_OVERFL=DEFAULT\"" << endl ;
488 first_time = first_time & (~ 2) ;
493 //==== Save the old Signal Handler, and set the new one ===================
495 sigemptyset(&act.sa_mask) ;
498 act.sa_flags = SA_RESTART ;
503 act.sa_flags = act.sa_flags | SA_SIGINFO ;
504 act.sa_sigaction = /*(void(*)(int, siginfo_t *, void*))*/ Handler;
506 act.sa_handler = /*(SIG_PFV)*/ Handler;
509 //==== Always detected the signal "SIGFPE" =================================
510 stat = sigaction(SIGFPE,&act,&oact); // ...... floating point exception
512 cerr << "sigaction does not work !!! KO " << endl;
513 perror("sigaction ");
516 //==== Detected the only the "free" signals ================================
517 sigaction(SIGHUP,&act,&oact); // ...... hangup
521 sigaction(SIGHUP,&oact,&oact);
524 sigaction(SIGINT,&act,&oact); // ...... interrupt
528 sigaction(SIGINT,&oact,&oact);
531 sigaction(SIGQUIT,&act,&oact); // ...... quit
535 sigaction(SIGQUIT,&oact,&oact);
538 sigaction(SIGILL,&act,&oact); // ...... illegal instruction
542 sigaction(SIGILL,&oact,&oact);
545 sigaction(SIGBUS,&act,&oact); // ...... bus error
549 sigaction(SIGBUS,&oact,&oact);
552 #if (!defined (linux)) && (!defined(LININTEL))
553 sigaction(SIGSYS,&act,&oact); // ...... bad argument to system call
557 sigaction(SIGSYS,&oact,&oact);
561 #if defined (__sgi) || defined(IRIX)
562 sigaction(SIGTRAP,&act,&oact); // Integer Divide By Zero (IRIX)
566 sigaction(SIGTRAP,&oact,&oact);
571 act.sa_sigaction = /*(void(*)(int, siginfo_t *, void*))*/ SegvHandler;
573 act.sa_handler = /*(SIG_PFV)*/ SegvHandler;
576 if ( sigaction( SIGSEGV , &act , &oact ) ) // ...... segmentation violation
577 perror("OSD::SetSignal sigaction( SIGSEGV , &act , &oact ) ") ;
581 sigaction(SIGSEGV,&oact,&oact);
583 #if defined(__osf__) || defined(DECOSF1)
584 struct sigaction action, prev_action;
585 action.sa_handler = SIG_IGN;
589 if (sigaction (SIGFPE, &action, &prev_action) == -1) {
590 perror ("sigaction");
597 //============================================================================
599 //============================================================================
601 void OSD :: ControlBreak ()
604 fCtrlBrk = Standard_False;
605 OSD_Exception_CTRL_BREAK::Raise ("*** INTERRUPT ***");