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