0025418: Debug output to be limited to OCC development environment
[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);
0797d9d3 190#ifdef OCCT_DEBUG
89c4bca8 191 cerr << " previous signal handler return" << endl ;
63c629aa 192#endif
89c4bca8 193 return;
7fd59977 194 }
195 else {
196 // cout << "OSD::Handler: no handler with info for the signal" << endl;
197 }
89c4bca8 198 }
199 else {
200 // no siginfo needed for the signal
7fd59977 201 void (*aCurHandler) (int) = asigacthandler.sa_handler;
202 if(aCurHandler) {
89c4bca8 203 // cout << "OSD::Handler: calling previous signal handler" << endl ;
204 (*aCurHandler) (theSignal);
0797d9d3 205#ifdef OCCT_DEBUG
89c4bca8 206 cerr << " previous signal handler return" << endl ;
63c629aa 207#endif
89c4bca8 208 return;
209 }
7fd59977 210 }
211 // cout << " Signal occured outside a try block, but no handler for it" <<endl;
212 return;
213 }
214#endif
215
7fd59977 216 // cout << "OSD::Handler: signal " << (int) theSignal << " occured inside a try block " << endl ;
89c4bca8 217 if ( ADR_ACT_SIGIO_HANDLER != NULL )
218 (*ADR_ACT_SIGIO_HANDLER)() ;
7fd59977 219#ifdef linux
220 if (fFltExceptions)
221 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
222 //feenableexcept (FE_INVALID | FE_DIVBYZERO);
223#endif
7fd59977 224 sigset_t set;
225 sigemptyset(&set);
89c4bca8 226 switch (theSignal) {
7fd59977 227 case SIGHUP:
228 OSD_SIGHUP::NewInstance("SIGHUP 'hangup' detected.")->Jump();
229 exit(SIGHUP);
230 break;
7fd59977 231 case SIGINT:
8a262fa1 232 // For safe handling of Control-C as stop event, arm a variable but do not
233 // generate longjump (we are out of context anyway)
234 fCtrlBrk = Standard_True;
89c4bca8 235 // OSD_SIGINT::NewInstance("SIGINT 'interrupt' detected.")->Jump();
236 // exit(SIGINT);
7fd59977 237 break;
7fd59977 238 case SIGQUIT:
239 OSD_SIGQUIT::NewInstance("SIGQUIT 'quit' detected.")->Jump();
240 exit(SIGQUIT);
241 break;
7fd59977 242 case SIGILL:
243 OSD_SIGILL::NewInstance("SIGILL 'illegal instruction' detected.")->Jump();
244 exit(SIGILL);
245 break;
7fd59977 246 case SIGKILL:
247 OSD_SIGKILL::NewInstance("SIGKILL 'kill' detected.")->Jump();
248 exit(SIGKILL);
249 break;
7fd59977 250 case SIGBUS:
251 sigaddset(&set, SIGBUS);
252 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
253 OSD_SIGBUS::NewInstance("SIGBUS 'bus error' detected.")->Jump();
254 exit(SIGBUS);
255 break;
7fd59977 256 case SIGSEGV:
257 OSD_SIGSEGV::NewInstance("SIGSEGV 'segmentation violation' detected.")->Jump();
258 exit(SIGSEGV);
259 break;
7fd59977 260#ifdef SIGSYS
261 case SIGSYS:
262 OSD_SIGSYS::NewInstance("SIGSYS 'bad argument to system call' detected.")->Jump();
263 exit(SIGSYS);
264 break;
265#endif
89c4bca8 266 case SIGFPE:
7fd59977 267 sigaddset(&set, SIGFPE);
268 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
269#ifdef DECOSF1
89c4bca8 270 // Pour DEC/OSF1 SIGFPE = Division par zero.
7fd59977 271 Standard_DivideByZero::NewInstance('')->Jump;
7fd59977 272 break;
89c4bca8 273#endif
7fd59977 274#if (!defined (__sun)) && (!defined(SOLARIS))
275 Standard_NumericError::NewInstance("SIGFPE Arithmetic exception detected")->Jump();
276 break;
277#else
278 // Reste SOLARIS
89c4bca8 279 if (aSigInfo) {
7fd59977 280 switch(aSigInfo->si_code) {
281 case FPE_FLTDIV_TRAP :
89c4bca8 282 Standard_DivideByZero::NewInstance("Floating Divide By Zero")->Jump();
283 break;
7fd59977 284 case FPE_INTDIV_TRAP :
89c4bca8 285 Standard_DivideByZero::NewInstance("Integer Divide By Zero")->Jump();
286 break;
7fd59977 287 case FPE_FLTOVF_TRAP :
89c4bca8 288 Standard_Overflow::NewInstance("Floating Overflow")->Jump();
289 break;
7fd59977 290 case FPE_INTOVF_TRAP :
89c4bca8 291 Standard_Overflow::NewInstance("Integer Overflow")->Jump();
292 break;
7fd59977 293 case FPE_FLTUND_TRAP :
89c4bca8 294 Standard_NumericError::NewInstance("Floating Underflow")->Jump();
295 break;
7fd59977 296 case FPE_FLTRES_TRAP:
89c4bca8 297 Standard_NumericError::NewInstance("Floating Point Inexact Result")->Jump();
298 break;
7fd59977 299 case FPE_FLTINV_TRAP :
89c4bca8 300 Standard_NumericError::NewInstance("Invalid Floating Point Operation")->Jump();
301 break;
7fd59977 302 default:
89c4bca8 303 Standard_NumericError::NewInstance("Numeric Error")->Jump();
304 break;
7fd59977 305 }
89c4bca8 306 } else {
7fd59977 307 Standard_NumericError::NewInstance("SIGFPE Arithmetic exception detected")->Jump();
308 }
309#endif
310 break;
7fd59977 311#if defined (__sgi) || defined(IRIX)
89c4bca8 312 case SIGTRAP:
7fd59977 313 sigaddset(&set, SIGTRAP);
314 sigprocmask(SIG_UNBLOCK, &set, NULL) ;
315 Standard_DivideByZero::NewInstance("SIGTRAP IntegerDivideByZero")->Jump(); break;
316#endif
317 default:
0797d9d3 318#ifdef OCCT_DEBUG
89c4bca8 319 cout << "Unexpected signal " << theSignal << endl ;
63c629aa 320#endif
89c4bca8 321 break;
8a262fa1 322 }
323}
324
7fd59977 325//============================================================================
89c4bca8 326//==== SegvHandler
7fd59977 327//============================================================================
7fd59977 328#ifdef SA_SIGINFO
329
89c4bca8 330static void SegvHandler(const int theSignal,
331 siginfo_t *ip,
332 const Standard_Address theContext)
7fd59977 333{
89c4bca8 334#ifdef NO_CXX_EXCEPTION
7fd59977 335 if (!Standard_ErrorHandler::IsInTryBlock()) {
89c4bca8 336 Handler(theSignal, ip, theContext);
7fd59977 337 return;
338 }
7fd59977 339#endif
7fd59977 340#ifdef linux
341 if (fFltExceptions)
342 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
343 //feenableexcept (FE_INVALID | FE_DIVBYZERO);
344#endif
7fd59977 345// cout << "OSD::SegvHandler activated(SA_SIGINFO)" << endl ;
346 if ( ip != NULL ) {
347 sigset_t set;
348 sigemptyset(&set);
349 sigaddset(&set, SIGSEGV);
350 sigprocmask (SIG_UNBLOCK, &set, NULL) ;
89c4bca8 351 void *address = ip->si_addr ;
4d9421a9 352 {
7fd59977 353 char Msg[100];
354 sprintf(Msg,"SIGSEGV 'segmentation violation' detected. Address %lx",
89c4bca8 355 (long ) address ) ;
7fd59977 356 OSD_SIGSEGV::NewInstance(Msg)->Jump();
357 }
89c4bca8 358 }
0797d9d3 359#ifdef OCCT_DEBUG
89c4bca8 360 else {
7fd59977 361 cout << "Wrong undefined address." << endl ;
89c4bca8 362 }
63c629aa 363#endif
7fd59977 364 exit(SIGSEGV);
365}
366
89c4bca8 367#elif defined (_hpux) || defined(HPUX)
7fd59977 368// Not ACTIVE ? SA_SIGINFO is defined on SUN, OSF, SGI and HP (and Linux) !
369// pour version 09.07
89c4bca8 370
371static void SegvHandler(const int theSignal,
372 siginfo_t *ip,
373 const Standard_Address theContext)
7fd59977 374{
375 unsigned long Space ;
376 unsigned long Offset ;
377 char Msg[100] ;
378
89c4bca8 379 if ( theContext != NULL ) {
380 Space = ((struct sigcontext *)theContext)->sc_sl.sl_ss.ss_cr20 ;
381 Offset = ((struct sigcontext *)theContext)->sc_sl.sl_ss.ss_cr21 ;
7fd59977 382// cout << "Wrong address = " << hex(Offset) << endl ;
4d9421a9 383 {
89c4bca8 384 sprintf(Msg,"SIGSEGV 'segmentation violation' detected. Address %lx",Offset) ;
385 OSD_SIGSEGV::Jump(Msg);
7fd59977 386// scp->sc_pcoq_head = scp->sc_pcoq_tail ; Permettrait de continuer a
387// scp->sc_pcoq_tail = scp->sc_pcoq_tail + 0x4 ; l'intruction suivant le segv.
388 }
389 }
0797d9d3 390#ifdef OCCT_DEBUG
89c4bca8 391 else {
7fd59977 392 cout << "Wrong undefined address." << endl ;
89c4bca8 393 }
63c629aa 394#endif
7fd59977 395 exit(SIGSEGV);
89c4bca8 396}
397
398#endif
399
400//============================================================================
401//==== SetSignal
402//==== Set the differents signals:
403//============================================================================
404
405void OSD::SetSignal(const Standard_Boolean aFloatingSignal)
406{
407 static int first_time = 3 ;
408 struct sigaction act, oact;
409 int stat = 0;
410
411 if( aFloatingSignal ) {
412 //==== Enable the floating point exceptions ===============
413#if defined (__sun) || defined (SOLARIS)
414 sigfpe_handler_type PHandler = (sigfpe_handler_type) Handler ;
415 stat = ieee_handler("set", "invalid", PHandler);
416 stat = ieee_handler("set", "division", PHandler) || stat;
417 stat = ieee_handler("set", "overflow", PHandler) || stat;
418
419 //stat = ieee_handler("set", "underflow", PHandler) || stat;
420 //stat = ieee_handler("set", "inexact", PHandler) || stat;
421
422 if (stat) {
0797d9d3 423#ifdef OCCT_DEBUG
89c4bca8 424 cerr << "ieee_handler does not work !!! KO " << endl;
63c629aa 425#endif
89c4bca8 426 }
427#elif defined (linux)
428 feenableexcept (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
429 //feenableexcept (FE_INVALID | FE_DIVBYZERO);
430 fFltExceptions = Standard_True;
431#endif
432 }
433 else if ( first_time & 1 ) {
434// cout << "SetSignal( Standard_False ) is not implemented..." << endl ;
435 first_time = first_time & (~ 1) ;
436 }
437
438#if defined (sgi) || defined (IRIX )
439 if ( first_time & 2 ) {
440 char *TRAP_FPE = getenv("TRAP_FPE") ;
441 if ( TRAP_FPE == NULL ) {
0797d9d3 442#ifdef OCCT_DEBUG
89c4bca8 443 cout << "On SGI you must set TRAP_FPE environment variable : " << endl ;
444 cout << "set env(TRAP_FPE) \"UNDERFL=FLUSH_ZERO;OVERFL=DEFAULT;DIVZERO=DEFAULT;INT_OVERFL=DEFAULT\" or" << endl ;
445 cout << "setenv TRAP_FPE \"UNDERFL=FLUSH_ZERO;OVERFL=DEFAULT;DIVZERO=DEFAULT;INT_OVERFL=DEFAULT\"" << endl ;
63c629aa 446#endif
89c4bca8 447// exit(1) ;
448 first_time = first_time & (~ 2) ;
449 }
450 }
451#endif
452
453 //==== Save the old Signal Handler, and set the new one ===================
454
455 sigemptyset(&act.sa_mask) ;
456
457#ifdef SA_RESTART
458 act.sa_flags = SA_RESTART ;
459#else
460 act.sa_flags = 0 ;
461#endif
462#ifdef SA_SIGINFO
463 act.sa_flags = act.sa_flags | SA_SIGINFO ;
464 act.sa_sigaction = /*(void(*)(int, siginfo_t *, void*))*/ Handler;
465#else
466 act.sa_handler = /*(SIG_PFV)*/ Handler;
467#endif
7fd59977 468
89c4bca8 469 //==== Always detected the signal "SIGFPE" =================================
470 stat = sigaction(SIGFPE,&act,&oact); // ...... floating point exception
471 if (stat) {
0797d9d3 472#ifdef OCCT_DEBUG
89c4bca8 473 cerr << "sigaction does not work !!! KO " << endl;
63c629aa 474#endif
89c4bca8 475 perror("sigaction ");
476 }
477
478 //==== Detected the only the "free" signals ================================
479 sigaction(SIGHUP,&act,&oact); // ...... hangup
480
481#ifdef OBJS
482 if(oact.sa_handler)
483 sigaction(SIGHUP,&oact,&oact);
484#endif
485
486 sigaction(SIGINT,&act,&oact); // ...... interrupt
487
488#ifdef OBJS
489 if(oact.sa_handler)
490 sigaction(SIGINT,&oact,&oact);
7fd59977 491#endif
89c4bca8 492
493 sigaction(SIGQUIT,&act,&oact); // ...... quit
494
495#ifdef OBJS
496 if(oact.sa_handler)
497 sigaction(SIGQUIT,&oact,&oact);
498#endif
499
500 sigaction(SIGILL,&act,&oact); // ...... illegal instruction
501
502#ifdef OBJS
503 if(oact.sa_handler)
504 sigaction(SIGILL,&oact,&oact);
505#endif
506
507 sigaction(SIGBUS,&act,&oact); // ...... bus error
508
509#ifdef OBJS
510 if(oact.sa_handler)
511 sigaction(SIGBUS,&oact,&oact);
512#endif
513
514#if (!defined (linux)) && (!defined(LININTEL))
515 sigaction(SIGSYS,&act,&oact); // ...... bad argument to system call
516
517# ifdef OBJS
518 if(oact.sa_handler)
519 sigaction(SIGSYS,&oact,&oact);
520# endif
521#endif
522
523#if defined (__sgi) || defined(IRIX)
524 sigaction(SIGTRAP,&act,&oact); // Integer Divide By Zero (IRIX)
525
526# ifdef OBJS
527 if(oact.sa_handler)
528 sigaction(SIGTRAP,&oact,&oact);
529# endif
530#endif
531
532#ifdef SA_SIGINFO
533 act.sa_sigaction = /*(void(*)(int, siginfo_t *, void*))*/ SegvHandler;
7fd59977 534#else
89c4bca8 535 act.sa_handler = /*(SIG_PFV)*/ SegvHandler;
536#endif
7fd59977 537
89c4bca8 538 if ( sigaction( SIGSEGV , &act , &oact ) ) // ...... segmentation violation
539 perror("OSD::SetSignal sigaction( SIGSEGV , &act , &oact ) ") ;
7fd59977 540
89c4bca8 541#ifdef OBJS
542 if(oact.sa_handler)
543 sigaction(SIGSEGV,&oact,&oact);
544#endif
545#if defined(__osf__) || defined(DECOSF1)
546 struct sigaction action, prev_action;
547 action.sa_handler = SIG_IGN;
548 action.sa_mask = 0;
549 action.sa_flags = 0;
550
551 if (sigaction (SIGFPE, &action, &prev_action) == -1) {
552 perror ("sigaction");
553 exit (1);
554 }
7fd59977 555#endif
89c4bca8 556
557}
558
559//============================================================================
560//==== ControlBreak
561//============================================================================
562
563void OSD :: ControlBreak ()
564{
565 if ( fCtrlBrk ) {
566 fCtrlBrk = Standard_False;
567 OSD_Exception_CTRL_BREAK::Raise ("*** INTERRUPT ***");
568 }
569}
570
7fd59977 571#endif