1 // Copyright (c) 1999-2012 OPEN CASCADE SAS
3 // The content of this file is subject to the Open CASCADE Technology Public
4 // License Version 6.5 (the "License"). You may not use the content of this file
5 // except in compliance with the License. Please obtain a copy of the License
6 // at http://www.opencascade.org and read it completely before using this file.
8 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
9 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11 // The Original Code and all software distributed under the License is
12 // distributed on an "AS IS" basis, without warranty of any kind, and the
13 // Initial Developer hereby disclaims all such warranties, including without
14 // limitation, any warranties of merchantability, fitness for a particular
15 // purpose or non-infringement. Please see the License for the specific terms
16 // and conditions governing the rights and limitations under the License.
23 //---------- All Systems except Windows NT : ----------------------------------
31 #include <OSD_WhoAmI.hxx>
32 #include <OSD_SIGHUP.hxx>
33 #include <OSD_SIGINT.hxx>
34 #include <OSD_SIGQUIT.hxx>
35 #include <OSD_SIGILL.hxx>
36 #include <OSD_SIGKILL.hxx>
37 #include <OSD_SIGBUS.hxx>
38 #include <OSD_SIGSEGV.hxx>
39 #include <OSD_SIGSYS.hxx>
40 #include <OSD_Exception_CTRL_BREAK.hxx>
41 #include <Standard_NumericError.hxx>
42 #include <Standard_NullObject.hxx>
43 #include <Standard_DivideByZero.hxx>
44 #include <Standard_Overflow.hxx>
46 #include <Standard_ErrorHandler.hxx>
54 static pthread_t getOCCThread () {
55 static pthread_t TheOCCThread = 0;
62 #include <fpu_control.h>
63 static Standard_Boolean fFltExceptions = Standard_False;
66 // variable signalling that Control-C has been pressed (SIGINT signal)
67 static Standard_Boolean fCtrlBrk;
69 //const OSD_WhoAmI Iam = OSD_WPackage;
71 typedef void (ACT_SIGIO_HANDLER)(void) ;
72 ACT_SIGIO_HANDLER *ADR_ACT_SIGIO_HANDLER = NULL ;
74 #if defined(HAVE_FLOATINGPOINT_H) && defined(HAVE_SYS_MACHSIG_H)
75 # include <floatingpoint.h>
76 # include <sys/machsig.h>
77 // JPT : Difference between SUN/SUNOS and SUN/SOLARIS
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
84 #define FPE_FLTRES_TRAP FPE_FLTRES /* floating point inexact result */
85 #define FPE_FLTINV_TRAP FPE_FLTINV /* invalid floating point operation */
86 #define FPE_FLTSUB_TRAP FPE_FLTSUB /* subscript out of range */
88 extern "C" {int ieee_handler(char *,char *, sigfpe_handler_type&);}
93 typedef void (* SIG_PFV) (int);
96 #if defined(HAVE_SIGFPE_H) && defined(HAVE_SYS_SIGINFO_H)
98 # include <sys/siginfo.h>
99 # define FPE_FLTDIV_TRAP FPE_FLTDIV
100 # define FPE_INTDIV_TRAP FPE_INTDIV
101 # define FPE_FLTOVF_TRAP FPE_FLTOVF
102 # define FPE_INTOVF_TRAP FPE_INTOVF
103 # define FPE_FLTUND_TRAP FPE_FLTUND
112 # include <sys/siginfo.h>
116 typedef void (* SIG_PFV) (int);
122 #ifdef HAVE_SYS_SIGNAL_H
123 # include <sys/signal.h>
126 #if defined(HAVE_PTHREAD_H) && defined(NO_CXX_EXCEPTION)
127 //============================================================================
128 //==== GetOldSigAction
130 //============================================================================
132 static struct sigaction *GetOldSigAction()
134 static struct sigaction oldSignals[NSIG];
139 static sigfpe_handler_type *GetOldFPE()
141 static sigfpe_handler_type aIEEEHandler[5] = { NULL, NULL, NULL, NULL, NULL } ;
148 //============================================================================
150 //==== Set the differents signals:
151 //============================================================================
153 void OSD::SetSignal(const Standard_Boolean aFloatingSignal)
155 static int first_time = 3 ;
156 struct sigaction act, oact;
159 if( aFloatingSignal ) {
160 //==== Enable the floating point exceptions ===============
161 #if defined (__sun) || defined (SOLARIS)
162 sigfpe_handler_type PHandler = (sigfpe_handler_type) Handler ;
163 stat = ieee_handler("set", "invalid", PHandler);
164 stat = ieee_handler("set", "division", PHandler) || stat;
165 stat = ieee_handler("set", "overflow", PHandler) || stat;
166 //stat = ieee_handler("set", "underflow", PHandler) || stat;
167 //stat = ieee_handler("set", "inexact", PHandler) || stat;
169 cerr << "ieee_handler does not work !!! KO " << endl;
171 #elif defined (linux)
172 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
173 //feenableexcept (FE_INVALID | FE_DIVBYZERO);
174 fFltExceptions = Standard_True;
177 else if ( first_time & 1 ) {
178 // cout << "SetSignal( Standard_False ) is not implemented..." << endl ;
179 first_time = first_time & (~ 1) ;
182 #if defined (sgi) || defined (IRIX )
183 if ( first_time & 2 ) {
184 char *TRAP_FPE = getenv("TRAP_FPE") ;
185 if ( TRAP_FPE == NULL ) {
186 cout << "On SGI you must set TRAP_FPE environment variable : " << endl ;
187 cout << "set env(TRAP_FPE) \"UNDERFL=FLUSH_ZERO;OVERFL=DEFAULT;DIVZERO=DEFAULT;INT_OVERFL=DEFAULT\" or" << endl ;
188 cout << "setenv TRAP_FPE \"UNDERFL=FLUSH_ZERO;OVERFL=DEFAULT;DIVZERO=DEFAULT;INT_OVERFL=DEFAULT\"" << endl ;
190 first_time = first_time & (~ 2) ;
195 //==== Save the old Signal Handler, and set the new one ===================
197 sigemptyset(&act.sa_mask) ;
200 act.sa_flags = SA_RESTART ;
205 act.sa_flags = act.sa_flags | SA_SIGINFO ;
206 act.sa_sigaction = (void(*)(int, siginfo_t *, void*)) &Handler ;
208 act.sa_handler = (SIG_PFV) &Handler ;
211 //==== Always detected the signal "SIGFPE" =================================
212 stat = sigaction(SIGFPE,&act,&oact); // ...... floating point exception
214 cerr << "sigaction does not work !!! KO " << endl;
215 perror("sigaction ");
218 //==== Detected the only the "free" signals ================================
219 sigaction(SIGHUP,&act,&oact); // ...... hangup
223 sigaction(SIGHUP,&oact,&oact);
226 sigaction(SIGINT,&act,&oact); // ...... interrupt
230 sigaction(SIGINT,&oact,&oact);
233 sigaction(SIGQUIT,&act,&oact); // ...... quit
237 sigaction(SIGQUIT,&oact,&oact);
240 sigaction(SIGILL,&act,&oact); // ...... illegal instruction
244 sigaction(SIGILL,&oact,&oact);
247 sigaction(SIGBUS,&act,&oact); // ...... bus error
251 sigaction(SIGBUS,&oact,&oact);
254 #if (!defined (linux)) && (!defined(LININTEL))
255 sigaction(SIGSYS,&act,&oact); // ...... bad argument to system call
259 sigaction(SIGSYS,&oact,&oact);
263 #if defined (__sgi) || defined(IRIX)
264 sigaction(SIGTRAP,&act,&oact); // Integer Divide By Zero (IRIX)
268 sigaction(SIGTRAP,&oact,&oact);
273 act.sa_sigaction = (void(*)(int, siginfo_t *, void*)) &SegvHandler ;
275 act.sa_handler = (SIG_PFV) &SegvHandler ;
278 if ( sigaction( SIGSEGV , &act , &oact ) ) // ...... segmentation violation
279 perror("OSD::SetSignal sigaction( SIGSEGV , &act , &oact ) ") ;
283 sigaction(SIGSEGV,&oact,&oact);
285 #if defined(__osf__) || defined(DECOSF1)
286 struct sigaction action, prev_action;
287 action.sa_handler = SIG_IGN;
291 if (sigaction (SIGFPE, &action, &prev_action) == -1) {
292 perror ("sigaction");
298 //============================================================================
300 //==== Catche the differents signals:
301 //==== 1- The Fatal signals, which cause the end of process:
302 //==== 2- The exceptions which are "signaled" by Raise.
303 //==== The Fatal Signals:
304 //==== SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGKILL, SIGBUS, SIGSYS
305 //==== The Exceptions:
307 //==== (SUN versions)
308 //==== FPE_INTOVF_TRAP // ..... integer overflow
309 //==== FPE_INTDIV_TRAP // ..... integer divide by zero
310 //==== FPE_FLTINEX_TRAP // ..... [floating inexact result]
311 //==== FPE_FLTDIV_TRAP // ..... [floating divide by zero]
312 //==== FPE_FLTUND_TRAP // ..... [floating underflow]
313 //==== FPE_FLTOPER_TRAP // ..... [floating inexact result]
314 //==== FPE_FLTOVF_TRAP // ..... [floating overflow]
315 //==== SIGSEGV is handled by "SegvHandler()"
316 //============================================================================
319 void OSD::Handler(const OSD_Signals theSignal,
320 const Standard_Address
324 ,const Standard_Address
325 #if defined(HAVE_PTHREAD_H) && defined(NO_CXX_EXCEPTION)
330 struct sigaction oldact, act;
332 // re-install the signal
334 if ( ! sigaction (theSignal, NULL, &oldact) ) {
335 // cout << " signal is " << theSignal << " handler is " << oldact.sa_handler << endl;
336 if (sigaction (theSignal, &oldact, &act)) perror ("sigaction");
339 perror ("sigaction");
341 siginfo_t * aSigInfo = NULL;
343 aSigInfo = (siginfo_t *) theSigInfo;
346 #if defined(HAVE_PTHREAD_H) && defined(NO_CXX_EXCEPTION)
349 // cout << " current thread " << pthread_self() << endl;
353 if (pthread_self() != getOCCThread() || !Standard_ErrorHandler::IsInTryBlock()) {
354 // use the previous signal handler
355 // cout << "OSD::Handler: signal " << (int) theSignal << " occured outside a try block " << endl ;
357 struct sigaction *oldSignals = GetOldSigAction();
358 struct sigaction asigacthandler = oldSignals[(int) theSignal];
360 if (asigacthandler.sa_flags & SA_SIGINFO) {
361 void (*aCurInfoHandle)(int, siginfo_t *, void *) = asigacthandler.sa_sigaction;
363 switch (aSigInfo->si_signo) {
367 sigfpe_handler_type *aIEEEHandlerTab = GetOldFPE();
368 sigfpe_handler_type aIEEEHandler = NULL;
370 switch (aSigInfo->si_code) {
371 case FPE_INTDIV_TRAP :
372 case FPE_FLTDIV_TRAP :
373 aIEEEHandler = aIEEEHandlerTab[1];
375 case FPE_INTOVF_TRAP :
376 case FPE_FLTOVF_TRAP :
377 aIEEEHandler = aIEEEHandlerTab[2];
379 case FPE_FLTUND_TRAP :
380 aIEEEHandler = aIEEEHandlerTab[4];
382 case FPE_FLTRES_TRAP:
383 aIEEEHandler = aIEEEHandlerTab[3];
385 case FPE_FLTINV_TRAP :
386 aIEEEHandler = aIEEEHandlerTab[0];
388 case FPE_FLTSUB_TRAP :
393 // cout << "OSD::Handler: calling previous IEEE signal handler with info" << endl ;
394 void (*aFPEHandler)(int, siginfo_t *, void *) = (void(*)(int, siginfo*, void*)) aIEEEHandler;
395 (*aFPEHandler) (theSignal, aSigInfo, theContext);
402 switch (aSigInfo->si_code) {
404 // cout << "OSD::Handler: SIGSEGV signal : address not mapped to object";
407 // cout << "OSD::Handler: SIGSEGV signal : invalid permissions for mapped object";
410 // cout << "OSD::Handler: SIGSEGV signal : unknown segv";
413 // cout << " at address " << (void *) aSigInfo->si_addr << endl;
416 switch (aSigInfo->si_code) {
418 // cout << "OSD::Handler: SIGBUS signal : invalid address alignment";
421 // cout << "OSD::Handler: SIGBUS signal : non-existent physical address";
424 // cout << "OSD::Handler: SIGBUS signal : object specific hardware error";
427 // cout << "OSD::Handler: SIGBUS signal : unknown sig bus";
430 // cout << " at " << (void *) aSigInfo->si_addr << endl;
433 // cout << "OSD::Handler: illegal instruction signal " << endl;
437 // cout << "OSD::Handler: bad argument to system call signal"<< endl ;
441 // cout << "OSD::Handler: interrupt signal" << endl;
447 if (aCurInfoHandle) {
448 // cout << "OSD::Handler: calling previous signal handler with info " << aCurInfoHandle << endl ;
449 (*aCurInfoHandle) (theSignal, aSigInfo, theContext);
450 cerr << " previous signal handler return" << endl ;
454 // cout << "OSD::Handler: no handler with info for the signal" << endl;
457 // no siginfi needed for the signal
458 void (*aCurHandler) (int) = asigacthandler.sa_handler;
460 // cout << "OSD::Handler: calling previous signal handler" << endl ;
461 (*aCurHandler) (theSignal);
462 cerr << " previous signal handler return" << endl ;
466 // cout << " Signal occured outside a try block, but no handler for it" <<endl;
472 // cout << "OSD::Handler: signal " << (int) theSignal << " occured inside a try block " << endl ;
474 if ( ADR_ACT_SIGIO_HANDLER != NULL ) (*ADR_ACT_SIGIO_HANDLER)() ;
478 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
479 //feenableexcept (FE_INVALID | FE_DIVBYZERO);
488 OSD_SIGHUP::NewInstance("SIGHUP 'hangup' detected.")->Jump();
493 // For safe handling of Control-C as stop event, arm a variable but do not
494 // generate longjump (we are out of context anyway)
495 fCtrlBrk = Standard_True;
496 // OSD_SIGINT::NewInstance("SIGINT 'interrupt' detected.")->Jump();
501 OSD_SIGQUIT::NewInstance("SIGQUIT 'quit' detected.")->Jump();
506 OSD_SIGILL::NewInstance("SIGILL 'illegal instruction' detected.")->Jump();
511 OSD_SIGKILL::NewInstance("SIGKILL 'kill' detected.")->Jump();
516 sigaddset(&set, SIGBUS);
517 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
518 OSD_SIGBUS::NewInstance("SIGBUS 'bus error' detected.")->Jump();
523 OSD_SIGSEGV::NewInstance("SIGSEGV 'segmentation violation' detected.")->Jump();
529 OSD_SIGSYS::NewInstance("SIGSYS 'bad argument to system call' detected.")->Jump();
536 sigaddset(&set, SIGFPE);
537 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
539 // Pour DEC/OSF1 SIGFPE = Division par zero.
540 // should be clarified why in debug mode only?
542 Standard_DivideByZero::NewInstance('')->Jump;
546 #if (!defined (__sun)) && (!defined(SOLARIS))
547 Standard_NumericError::NewInstance("SIGFPE Arithmetic exception detected")->Jump();
552 switch(aSigInfo->si_code) {
553 case FPE_FLTDIV_TRAP :
554 Standard_DivideByZero::NewInstance("Floating Divide By Zero")->Jump(); break;
555 case FPE_INTDIV_TRAP :
556 Standard_DivideByZero::NewInstance("Integer Divide By Zero")->Jump(); break;
557 case FPE_FLTOVF_TRAP :
558 Standard_Overflow::NewInstance("Floating Overflow")->Jump(); break;
559 case FPE_INTOVF_TRAP :
560 Standard_Overflow::NewInstance("Integer Overflow")->Jump(); break;
561 case FPE_FLTUND_TRAP :
562 Standard_NumericError::NewInstance("Floating Underflow")->Jump(); break;
563 case FPE_FLTRES_TRAP:
564 Standard_NumericError::NewInstance("Floating Point Inexact Result")->Jump(); break;
565 case FPE_FLTINV_TRAP :
566 Standard_NumericError::NewInstance("Invalid Floating Point Operation")->Jump(); break;
568 Standard_NumericError::NewInstance("Numeric Error")->Jump(); break;
572 Standard_NumericError::NewInstance("SIGFPE Arithmetic exception detected")->Jump();
577 #if defined (__sgi) || defined(IRIX)
579 sigaddset(&set, SIGTRAP);
580 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
581 Standard_DivideByZero::NewInstance("SIGTRAP IntegerDivideByZero")->Jump(); break;
584 cout << "Unexpected signal " << (Standard_Integer ) theSignal << endl ;
588 //============================================================================
590 //============================================================================
592 void OSD :: ControlBreak ()
595 fCtrlBrk = Standard_False;
596 OSD_Exception_CTRL_BREAK::Raise ("*** INTERRUPT ***");
600 //============================================================================
602 //============================================================================
606 #ifdef NO_CXX_EXCEPTION
607 void OSD::SegvHandler(const OSD_Signals theSig,
608 const Standard_Address ip,
609 const Standard_Address theContext)
611 if (!Standard_ErrorHandler::IsInTryBlock()) {
612 Handler(theSig, ip, theContext);
616 void OSD::SegvHandler(const OSD_Signals,
617 const Standard_Address ip,
618 const Standard_Address)
624 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
625 //feenableexcept (FE_INVALID | FE_DIVBYZERO);
628 // cout << "OSD::SegvHandler activated(SA_SIGINFO)" << endl ;
632 sigaddset(&set, SIGSEGV);
633 sigprocmask (SIG_UNBLOCK, &set, NULL) ;
634 void *address = ((siginfo_t *)ip)->si_addr ;
635 if ( (((long) address )& ~0xffff) == (long) UndefinedHandleAddress ) {
636 Standard_NullObject::NewInstance("Attempt to access to null object")->Jump();
640 sprintf(Msg,"SIGSEGV 'segmentation violation' detected. Address %lx",
642 OSD_SIGSEGV::NewInstance(Msg)->Jump();
646 cout << "Wrong undefined address." << endl ;
650 #if defined (_hpux) || defined(HPUX)
651 //============================================================================
653 //============================================================================
655 // Not ACTIVE ? SA_SIGINFO is defined on SUN, OSF, SGI and HP (and Linux) !
656 // pour version 09.07
657 void OSD::SegvHandler(const OSD_Signals aSig, const Standard_Address code,
658 const Standard_Address scp)
659 //void OSD::SegvHandler(const OSD_Signals aSig, int code, const Standard_Address scp)
661 unsigned long Space ;
662 unsigned long Offset ;
666 Space = ((struct sigcontext *)scp)->sc_sl.sl_ss.ss_cr20 ;
667 Offset = ((struct sigcontext *)scp)->sc_sl.sl_ss.ss_cr21 ;
668 // cout << "Wrong address = " << hex(Offset) << endl ;
669 if ((Offset & ~0xffff) == (long)UndefinedHandleAddress)
670 Standard_NullObject::Jump("Attempt to access to null object") ;
672 sprintf(Msg,"SIGSEGV 'segmentation violation' detected. Address %lx",Offset) ;
673 OSD_SIGSEGV::Jump(Msg);
674 // scp->sc_pcoq_head = scp->sc_pcoq_tail ; Permettrait de continuer a
675 // scp->sc_pcoq_tail = scp->sc_pcoq_tail + 0x4 ; l'intruction suivant le segv.
679 cout << "Wrong undefined address." << endl ;
685 // Must be there for compatibility with Windows NT system ---------------
687 Standard_Integer OSD :: WntHandler ( const Standard_Address )