6 //---------- All Systems except Windows NT : ----------------------------------
14 #include <OSD_WhoAmI.hxx>
15 #include <OSD_SIGHUP.hxx>
16 #include <OSD_SIGINT.hxx>
17 #include <OSD_SIGQUIT.hxx>
18 #include <OSD_SIGILL.hxx>
19 #include <OSD_SIGKILL.hxx>
20 #include <OSD_SIGBUS.hxx>
21 #include <OSD_SIGSEGV.hxx>
22 #include <OSD_SIGSYS.hxx>
23 #include <Standard_NumericError.hxx>
24 #include <Standard_NullObject.hxx>
25 #include <Standard_DivideByZero.hxx>
26 #include <Standard_Overflow.hxx>
28 #include <Standard_ErrorHandler.hxx>
36 static pthread_t getOCCThread () {
37 static pthread_t TheOCCThread = 0;
44 #include <fpu_control.h>
45 static Standard_Boolean fFltExceptions = Standard_False;
48 //const OSD_WhoAmI Iam = OSD_WPackage;
50 typedef void (ACT_SIGIO_HANDLER)(void) ;
51 ACT_SIGIO_HANDLER *ADR_ACT_SIGIO_HANDLER = NULL ;
53 #if defined(HAVE_FLOATINGPOINT_H) && defined(HAVE_SYS_MACHSIG_H)
54 # include <floatingpoint.h>
55 # include <sys/machsig.h>
56 // JPT : Difference between SUN/SUNOS and SUN/SOLARIS
57 # define FPE_FLTDIV_TRAP FPE_FLTDIV
58 # define FPE_INTDIV_TRAP FPE_INTDIV
59 # define FPE_FLTOVF_TRAP FPE_FLTOVF
60 # define FPE_INTOVF_TRAP FPE_INTOVF
61 # define FPE_FLTUND_TRAP FPE_FLTUND
63 #define FPE_FLTRES_TRAP FPE_FLTRES /* floating point inexact result */
64 #define FPE_FLTINV_TRAP FPE_FLTINV /* invalid floating point operation */
65 #define FPE_FLTSUB_TRAP FPE_FLTSUB /* subscript out of range */
67 extern "C" {int ieee_handler(char *,char *, sigfpe_handler_type&);}
72 typedef void (* SIG_PFV) (int);
75 #if defined(HAVE_SIGFPE_H) && defined(HAVE_SYS_SIGINFO_H)
77 # include <sys/siginfo.h>
78 # define FPE_FLTDIV_TRAP FPE_FLTDIV
79 # define FPE_INTDIV_TRAP FPE_INTDIV
80 # define FPE_FLTOVF_TRAP FPE_FLTOVF
81 # define FPE_INTOVF_TRAP FPE_INTOVF
82 # define FPE_FLTUND_TRAP FPE_FLTUND
91 # include <sys/siginfo.h>
95 typedef void (* SIG_PFV) (int);
101 #ifdef HAVE_SYS_SIGNAL_H
102 # include <sys/signal.h>
105 #if defined(HAVE_PTHREAD_H) && defined(NO_CXX_EXCEPTION)
106 //============================================================================
107 //==== GetOldSigAction
109 //============================================================================
111 static struct sigaction *GetOldSigAction()
113 static struct sigaction oldSignals[NSIG];
118 static sigfpe_handler_type *GetOldFPE()
120 static sigfpe_handler_type aIEEEHandler[5] = { NULL, NULL, NULL, NULL, NULL } ;
127 //============================================================================
129 //==== Set the differents signals:
130 //============================================================================
132 void OSD::SetSignal(const Standard_Boolean aFloatingSignal)
134 static int first_time = 3 ;
135 struct sigaction act, oact;
138 if( aFloatingSignal ) {
139 //==== Enable the floating point exceptions ===============
140 #if defined (__sun) || defined (SOLARIS)
141 sigfpe_handler_type PHandler = (sigfpe_handler_type) Handler ;
142 stat = ieee_handler("set", "invalid", PHandler);
143 stat = ieee_handler("set", "division", PHandler) || stat;
144 stat = ieee_handler("set", "overflow", PHandler) || stat;
145 //stat = ieee_handler("set", "underflow", PHandler) || stat;
146 //stat = ieee_handler("set", "inexact", PHandler) || stat;
148 cerr << "ieee_handler does not work !!! KO " << endl;
150 #elif defined (linux)
151 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
152 //feenableexcept (FE_INVALID | FE_DIVBYZERO);
153 fFltExceptions = Standard_True;
156 else if ( first_time & 1 ) {
157 // cout << "SetSignal( Standard_False ) is not implemented..." << endl ;
158 first_time = first_time & (~ 1) ;
161 #if defined (sgi) || defined (IRIX )
162 if ( first_time & 2 ) {
163 char *TRAP_FPE = getenv("TRAP_FPE") ;
164 if ( TRAP_FPE == NULL ) {
165 cout << "On SGI you must set TRAP_FPE environment variable : " << endl ;
166 cout << "set env(TRAP_FPE) \"UNDERFL=FLUSH_ZERO;OVERFL=DEFAULT;DIVZERO=DEFAULT;INT_OVERFL=DEFAULT\" or" << endl ;
167 cout << "setenv TRAP_FPE \"UNDERFL=FLUSH_ZERO;OVERFL=DEFAULT;DIVZERO=DEFAULT;INT_OVERFL=DEFAULT\"" << endl ;
169 first_time = first_time & (~ 2) ;
174 //==== Save the old Signal Handler, and set the new one ===================
176 sigemptyset(&act.sa_mask) ;
179 act.sa_flags = SA_RESTART ;
184 act.sa_flags = act.sa_flags | SA_SIGINFO ;
185 act.sa_sigaction = (void(*)(int, siginfo_t *, void*)) &Handler ;
187 act.sa_handler = (SIG_PFV) &Handler ;
190 //==== Always detected the signal "SIGFPE" =================================
191 stat = sigaction(SIGFPE,&act,&oact); // ...... floating point exception
193 cerr << "sigaction does not work !!! KO " << endl;
194 perror("sigaction ");
197 //==== Detected the only the "free" signals ================================
198 sigaction(SIGHUP,&act,&oact); // ...... hangup
202 sigaction(SIGHUP,&oact,&oact);
205 sigaction(SIGINT,&act,&oact); // ...... interrupt
209 sigaction(SIGINT,&oact,&oact);
212 sigaction(SIGQUIT,&act,&oact); // ...... quit
216 sigaction(SIGQUIT,&oact,&oact);
219 sigaction(SIGILL,&act,&oact); // ...... illegal instruction
223 sigaction(SIGILL,&oact,&oact);
226 sigaction(SIGBUS,&act,&oact); // ...... bus error
230 sigaction(SIGBUS,&oact,&oact);
233 #if (!defined (linux)) && (!defined(LININTEL))
234 sigaction(SIGSYS,&act,&oact); // ...... bad argument to system call
238 sigaction(SIGSYS,&oact,&oact);
242 #if defined (__sgi) || defined(IRIX)
243 sigaction(SIGTRAP,&act,&oact); // Integer Divide By Zero (IRIX)
247 sigaction(SIGTRAP,&oact,&oact);
252 act.sa_sigaction = (void(*)(int, siginfo_t *, void*)) &SegvHandler ;
254 act.sa_handler = (SIG_PFV) &SegvHandler ;
257 if ( sigaction( SIGSEGV , &act , &oact ) ) // ...... segmentation violation
258 perror("OSD::SetSignal sigaction( SIGSEGV , &act , &oact ) ") ;
262 sigaction(SIGSEGV,&oact,&oact);
264 #if defined(__osf__) || defined(DECOSF1)
265 struct sigaction action, prev_action;
266 action.sa_handler = SIG_IGN;
270 if (sigaction (SIGFPE, &action, &prev_action) == -1) {
271 perror ("sigaction");
277 //============================================================================
279 //==== Catche the differents signals:
280 //==== 1- The Fatal signals, which cause the end of process:
281 //==== 2- The exceptions which are "signaled" by Raise.
282 //==== The Fatal Signals:
283 //==== SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGKILL, SIGBUS, SIGSYS
284 //==== The Exceptions:
286 //==== (SUN versions)
287 //==== FPE_INTOVF_TRAP // ..... integer overflow
288 //==== FPE_INTDIV_TRAP // ..... integer divide by zero
289 //==== FPE_FLTINEX_TRAP // ..... [floating inexact result]
290 //==== FPE_FLTDIV_TRAP // ..... [floating divide by zero]
291 //==== FPE_FLTUND_TRAP // ..... [floating underflow]
292 //==== FPE_FLTOPER_TRAP // ..... [floating inexact result]
293 //==== FPE_FLTOVF_TRAP // ..... [floating overflow]
294 //==== SIGSEGV is handled by "SegvHandler()"
295 //============================================================================
298 void OSD::Handler(const OSD_Signals theSignal,
299 const Standard_Address
303 ,const Standard_Address
304 #if defined(HAVE_PTHREAD_H) && defined(NO_CXX_EXCEPTION)
309 struct sigaction oldact, act;
311 // re-install the signal
313 if ( ! sigaction (theSignal, NULL, &oldact) ) {
314 // cout << " signal is " << theSignal << " handler is " << oldact.sa_handler << endl;
315 if (sigaction (theSignal, &oldact, &act)) perror ("sigaction");
318 perror ("sigaction");
320 siginfo_t * aSigInfo = NULL;
322 aSigInfo = (siginfo_t *) theSigInfo;
325 #if defined(HAVE_PTHREAD_H) && defined(NO_CXX_EXCEPTION)
328 // cout << " current thread " << pthread_self() << endl;
332 if (pthread_self() != getOCCThread() || !Standard_ErrorHandler::IsInTryBlock()) {
333 // use the previous signal handler
334 // cout << "OSD::Handler: signal " << (int) theSignal << " occured outside a try block " << endl ;
336 struct sigaction *oldSignals = GetOldSigAction();
337 struct sigaction asigacthandler = oldSignals[(int) theSignal];
339 if (asigacthandler.sa_flags & SA_SIGINFO) {
340 void (*aCurInfoHandle)(int, siginfo_t *, void *) = asigacthandler.sa_sigaction;
342 switch (aSigInfo->si_signo) {
346 sigfpe_handler_type *aIEEEHandlerTab = GetOldFPE();
347 sigfpe_handler_type aIEEEHandler = NULL;
349 switch (aSigInfo->si_code) {
350 case FPE_INTDIV_TRAP :
351 case FPE_FLTDIV_TRAP :
352 aIEEEHandler = aIEEEHandlerTab[1];
354 case FPE_INTOVF_TRAP :
355 case FPE_FLTOVF_TRAP :
356 aIEEEHandler = aIEEEHandlerTab[2];
358 case FPE_FLTUND_TRAP :
359 aIEEEHandler = aIEEEHandlerTab[4];
361 case FPE_FLTRES_TRAP:
362 aIEEEHandler = aIEEEHandlerTab[3];
364 case FPE_FLTINV_TRAP :
365 aIEEEHandler = aIEEEHandlerTab[0];
367 case FPE_FLTSUB_TRAP :
372 // cout << "OSD::Handler: calling previous IEEE signal handler with info" << endl ;
373 void (*aFPEHandler)(int, siginfo_t *, void *) = (void(*)(int, siginfo*, void*)) aIEEEHandler;
374 (*aFPEHandler) (theSignal, aSigInfo, theContext);
381 switch (aSigInfo->si_code) {
383 // cout << "OSD::Handler: SIGSEGV signal : address not mapped to object";
386 // cout << "OSD::Handler: SIGSEGV signal : invalid permissions for mapped object";
389 // cout << "OSD::Handler: SIGSEGV signal : unknown segv";
392 // cout << " at address " << (void *) aSigInfo->si_addr << endl;
395 switch (aSigInfo->si_code) {
397 // cout << "OSD::Handler: SIGBUS signal : invalid address alignment";
400 // cout << "OSD::Handler: SIGBUS signal : non-existent physical address";
403 // cout << "OSD::Handler: SIGBUS signal : object specific hardware error";
406 // cout << "OSD::Handler: SIGBUS signal : unknown sig bus";
409 // cout << " at " << (void *) aSigInfo->si_addr << endl;
412 // cout << "OSD::Handler: illegal instruction signal " << endl;
416 // cout << "OSD::Handler: bad argument to system call signal"<< endl ;
420 // cout << "OSD::Handler: interrupt signal" << endl;
426 if (aCurInfoHandle) {
427 // cout << "OSD::Handler: calling previous signal handler with info " << aCurInfoHandle << endl ;
428 (*aCurInfoHandle) (theSignal, aSigInfo, theContext);
429 cerr << " previous signal handler return" << endl ;
433 // cout << "OSD::Handler: no handler with info for the signal" << endl;
436 // no siginfi needed for the signal
437 void (*aCurHandler) (int) = asigacthandler.sa_handler;
439 // cout << "OSD::Handler: calling previous signal handler" << endl ;
440 (*aCurHandler) (theSignal);
441 cerr << " previous signal handler return" << endl ;
445 // cout << " Signal occured outside a try block, but no handler for it" <<endl;
451 // cout << "OSD::Handler: signal " << (int) theSignal << " occured inside a try block " << endl ;
453 if ( ADR_ACT_SIGIO_HANDLER != NULL ) (*ADR_ACT_SIGIO_HANDLER)() ;
457 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
458 //feenableexcept (FE_INVALID | FE_DIVBYZERO);
467 OSD_SIGHUP::NewInstance("SIGHUP 'hangup' detected.")->Jump();
472 OSD_SIGINT::NewInstance("SIGINT 'interrupt' detected.")->Jump();
477 OSD_SIGQUIT::NewInstance("SIGQUIT 'quit' detected.")->Jump();
482 OSD_SIGILL::NewInstance("SIGILL 'illegal instruction' detected.")->Jump();
487 OSD_SIGKILL::NewInstance("SIGKILL 'kill' detected.")->Jump();
492 sigaddset(&set, SIGBUS);
493 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
494 OSD_SIGBUS::NewInstance("SIGBUS 'bus error' detected.")->Jump();
499 OSD_SIGSEGV::NewInstance("SIGSEGV 'segmentation violation' detected.")->Jump();
505 OSD_SIGSYS::NewInstance("SIGSYS 'bad argument to system call' detected.")->Jump();
512 sigaddset(&set, SIGFPE);
513 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
515 // Pour DEC/OSF1 SIGFPE = Division par zero.
516 // should be clarified why in debug mode only?
518 Standard_DivideByZero::NewInstance('')->Jump;
522 #if (!defined (__sun)) && (!defined(SOLARIS))
523 Standard_NumericError::NewInstance("SIGFPE Arithmetic exception detected")->Jump();
528 switch(aSigInfo->si_code) {
529 case FPE_FLTDIV_TRAP :
530 Standard_DivideByZero::NewInstance("Floating Divide By Zero")->Jump(); break;
531 case FPE_INTDIV_TRAP :
532 Standard_DivideByZero::NewInstance("Integer Divide By Zero")->Jump(); break;
533 case FPE_FLTOVF_TRAP :
534 Standard_Overflow::NewInstance("Floating Overflow")->Jump(); break;
535 case FPE_INTOVF_TRAP :
536 Standard_Overflow::NewInstance("Integer Overflow")->Jump(); break;
537 case FPE_FLTUND_TRAP :
538 Standard_NumericError::NewInstance("Floating Underflow")->Jump(); break;
539 case FPE_FLTRES_TRAP:
540 Standard_NumericError::NewInstance("Floating Point Inexact Result")->Jump(); break;
541 case FPE_FLTINV_TRAP :
542 Standard_NumericError::NewInstance("Invalid Floating Point Operation")->Jump(); break;
544 Standard_NumericError::NewInstance("Numeric Error")->Jump(); break;
548 Standard_NumericError::NewInstance("SIGFPE Arithmetic exception detected")->Jump();
553 #if defined (__sgi) || defined(IRIX)
555 sigaddset(&set, SIGTRAP);
556 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
557 Standard_DivideByZero::NewInstance("SIGTRAP IntegerDivideByZero")->Jump(); break;
560 cout << "Unexpected signal " << (Standard_Integer ) theSignal << endl ;
564 //============================================================================
566 //============================================================================
570 #ifdef NO_CXX_EXCEPTION
571 void OSD::SegvHandler(const OSD_Signals theSig,
572 const Standard_Address ip,
573 const Standard_Address theContext)
575 if (!Standard_ErrorHandler::IsInTryBlock()) {
576 Handler(theSig, ip, theContext);
580 void OSD::SegvHandler(const OSD_Signals,
581 const Standard_Address ip,
582 const Standard_Address)
588 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
589 //feenableexcept (FE_INVALID | FE_DIVBYZERO);
592 // cout << "OSD::SegvHandler activated(SA_SIGINFO)" << endl ;
596 sigaddset(&set, SIGSEGV);
597 sigprocmask (SIG_UNBLOCK, &set, NULL) ;
598 void *address = ((siginfo_t *)ip)->si_addr ;
599 if ( (((long) address )& ~0xffff) == (long) UndefinedHandleAddress ) {
600 Standard_NullObject::NewInstance("Attempt to access to null object")->Jump();
604 sprintf(Msg,"SIGSEGV 'segmentation violation' detected. Address %lx",
606 OSD_SIGSEGV::NewInstance(Msg)->Jump();
610 cout << "Wrong undefined address." << endl ;
614 #if defined (_hpux) || defined(HPUX)
615 //============================================================================
617 //============================================================================
619 // Not ACTIVE ? SA_SIGINFO is defined on SUN, OSF, SGI and HP (and Linux) !
620 // pour version 09.07
621 void OSD::SegvHandler(const OSD_Signals aSig, const Standard_Address code,
622 const Standard_Address scp)
623 //void OSD::SegvHandler(const OSD_Signals aSig, int code, const Standard_Address scp)
625 unsigned long Space ;
626 unsigned long Offset ;
630 Space = ((struct sigcontext *)scp)->sc_sl.sl_ss.ss_cr20 ;
631 Offset = ((struct sigcontext *)scp)->sc_sl.sl_ss.ss_cr21 ;
632 // cout << "Wrong address = " << hex(Offset) << endl ;
633 if ((Offset & ~0xffff) == (long)UndefinedHandleAddress)
634 Standard_NullObject::Jump("Attempt to access to null object") ;
636 sprintf(Msg,"SIGSEGV 'segmentation violation' detected. Address %lx",Offset) ;
637 OSD_SIGSEGV::Jump(Msg);
638 // scp->sc_pcoq_head = scp->sc_pcoq_tail ; Permettrait de continuer a
639 // scp->sc_pcoq_tail = scp->sc_pcoq_tail + 0x4 ; l'intruction suivant le segv.
643 cout << "Wrong undefined address." << endl ;
649 // Must be there for compatibility with Windows NT system ---------------
651 Standard_Integer OSD :: WntHandler ( const Standard_Address )