Geant4  10.01
G4FPEDetection.hh
Go to the documentation of this file.
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
27 // $Id: G4FPEDetection.hh 86793 2014-11-18 10:01:46Z gcosmo $
28 //
29 //
30 // -*- C++ -*-
31 //
32 // -----------------------------------------------------------------------
33 // This global method should be used on LINUX or MacOSX platforms with gcc
34 // compiler for activating NaN detection and FPE signals, and forcing
35 // abortion of the application at the time these are detected.
36 // Meant to be used for debug purposes, can be activated by compiling the
37 // "run" module with the flag G4FPE_DEBUG set in the environment.
38 // -----------------------------------------------------------------------
39 
40 #ifndef G4FPEDetection_h
41 #define G4FPEDetection_h 1
42 
43 #include <iostream>
44 #include <stdlib.h> /* abort(), exit() */
45 
46 #if (defined(__GNUC__) && !defined(__clang__))
47 #ifdef __linux__
48  #include <features.h>
49  #include <fenv.h>
50  #include <csignal>
51 // for G4StackBacktrace()
52  #include <execinfo.h>
53  #include <cxxabi.h>
54 
55  struct sigaction termaction, oldaction;
56 
57  static void G4StackBackTrace()
58  {
59 
60  // from http://linux.die.net/man/3/backtrace_symbols_fd
61  #define BSIZE 50
62  void * buffer[ BSIZE ];
63  int nptrs = backtrace( buffer, BSIZE );
64  //std::cerr << "nptrs=" << nptrs << std::endl;
65  char ** strings = backtrace_symbols( buffer, nptrs );
66  if ( strings == NULL ) {
67  perror( "backtrace_symbols" );
68  return;
69  }
70  std::cerr << std::endl<< "Call Stack:" << std::endl;
71  for ( int j = 0; j < nptrs; j++ ){
72  //printf("%s\n", strings[j]);
73  std::cerr << nptrs-j-1 <<": ";
74  //std::cerr << strings[j] << std::endl;
75  char * mangled_start = strchr( strings[j], '(' ) + 1;
76  if (mangled_start) *(mangled_start-1) = '\0';
77  char * mangled_end = strchr( mangled_start,'+' );
78  if ( mangled_end ) *mangled_end = '\0';
79  //std::cerr << "mangled .. " << mangled_start << ", len:" << strlen(mangled_start)<< std::endl;
80  int status = 0;
81  char *realname=0;
82  if ( mangled_end && strlen(mangled_start) )
83  realname = abi::__cxa_demangle( mangled_start, 0, 0, &status );
84  if ( realname ) {
85  std::cerr << strings[j]<< " : " << realname << std::endl;
86  free( realname );
87  } else {
88  std::cerr << strings[j] << std::endl;
89  }
90  }
91  free( strings );
92  // c++filt can demangle: http://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html
93  //-------------------------------------------------------------
94 
95  }
96  static void TerminationSignalHandler(int sig, siginfo_t* sinfo, void* /* context */)
97  {
98  std::cerr << "ERROR: " << sig;
99  std::string message = "Floating-point exception (FPE).";
100 
101  if (sinfo) {
102  switch (sinfo->si_code) {
103 #ifdef FPE_NOOP /* BUG: MacOSX uses this instead of INTDIV */
104  case FPE_NOOP:
105 #endif
106  case FPE_INTDIV:
107  message = "Integer divide by zero.";
108  break;
109  case FPE_INTOVF:
110  message = "Integer overflow.";
111  break;
112  case FPE_FLTDIV:
113  message = "Floating point divide by zero.";
114  break;
115  case FPE_FLTOVF:
116  message = "Floating point overflow.";
117  break;
118  case FPE_FLTUND:
119  message = "Floating point underflow.";
120  break;
121  case FPE_FLTRES:
122  message = "Floating point inexact result.";
123  break;
124  case FPE_FLTINV:
125  message = "Floating point invalid operation.";
126  break;
127  case FPE_FLTSUB:
128  message = "Subscript out of range.";
129  break;
130  default:
131  message = "Unknown error.";
132  break;
133  }
134  }
135 
136  std::cerr << " - " << message << std::endl;
137  G4StackBackTrace();
138  ::abort();
139  }
140 
141  static void InvalidOperationDetection()
142  {
143  std::cout << std::endl
144  << " "
145  << "############################################" << std::endl
146  << " "
147  << "!!! WARNING - FPE detection is activated !!!" << std::endl
148  << " "
149  << "############################################" << std::endl;
150 
151  (void) feenableexcept( FE_DIVBYZERO );
152  (void) feenableexcept( FE_INVALID );
153  //(void) feenableexcept( FE_OVERFLOW );
154  //(void) feenableexcept( FE_UNDERFLOW );
155 
156  sigfillset(&termaction.sa_mask);
157  sigdelset(&termaction.sa_mask,SIGFPE);
158  termaction.sa_sigaction=TerminationSignalHandler;
159  termaction.sa_flags=SA_SIGINFO;
160  sigaction(SIGFPE, &termaction, &oldaction);
161  }
162 
163 #elif defined(__MACH__) /* MacOSX */
164  #include <fenv.h>
165  #include <signal.h>
166 
167  #define DEFINED_PPC (defined(__ppc__) || defined(__ppc64__))
168  #define DEFINED_INTEL (defined(__i386__) || defined(__x86_64__))
169 
170  #if DEFINED_PPC
171 
172  #define FE_EXCEPT_SHIFT 22 // shift flags right to get masks
173  #define FM_ALL_EXCEPT FE_ALL_EXCEPT >> FE_EXCEPT_SHIFT
174 
175  static inline int feenableexcept (unsigned int excepts)
176  {
177  static fenv_t fenv;
178  unsigned int new_excepts = (excepts & FE_ALL_EXCEPT) >> FE_EXCEPT_SHIFT,
179  old_excepts; // all previous masks
180 
181  if ( fegetenv (&fenv) ) { return -1; }
182  old_excepts = (fenv & FM_ALL_EXCEPT) << FE_EXCEPT_SHIFT;
183  fenv = (fenv & ~new_excepts) | new_excepts;
184 
185  return ( fesetenv (&fenv) ? -1 : old_excepts );
186  }
187 
188  static inline int fedisableexcept (unsigned int excepts)
189  {
190  static fenv_t fenv;
191  unsigned int still_on = ~((excepts & FE_ALL_EXCEPT) >> FE_EXCEPT_SHIFT),
192  old_excepts; // previous masks
193 
194  if ( fegetenv (&fenv) ) { return -1; }
195  old_excepts = (fenv & FM_ALL_EXCEPT) << FE_EXCEPT_SHIFT;
196  fenv &= still_on;
197 
198  return ( fesetenv (&fenv) ? -1 : old_excepts );
199  }
200 
201  #elif DEFINED_INTEL
202 
203  static inline int feenableexcept (unsigned int excepts)
204  {
205  static fenv_t fenv;
206  unsigned int new_excepts = excepts & FE_ALL_EXCEPT,
207  old_excepts; // previous masks
208 
209  if ( fegetenv (&fenv) ) { return -1; }
210  old_excepts = fenv.__control & FE_ALL_EXCEPT;
211 
212  // unmask
213  //
214  fenv.__control &= ~new_excepts;
215  fenv.__mxcsr &= ~(new_excepts << 7);
216 
217  return ( fesetenv (&fenv) ? -1 : old_excepts );
218  }
219 
220  static inline int fedisableexcept (unsigned int excepts)
221  {
222  static fenv_t fenv;
223  unsigned int new_excepts = excepts & FE_ALL_EXCEPT,
224  old_excepts; // all previous masks
225 
226  if ( fegetenv (&fenv) ) { return -1; }
227  old_excepts = fenv.__control & FE_ALL_EXCEPT;
228 
229  // mask
230  //
231  fenv.__control |= new_excepts;
232  fenv.__mxcsr |= new_excepts << 7;
233 
234  return ( fesetenv (&fenv) ? -1 : old_excepts );
235  }
236 
237  #endif /* PPC or INTEL enabling */
238 
239  static void TerminationSignalHandler(int sig, siginfo_t* sinfo, void* /* context */)
240  {
241  std::cerr << "ERROR: " << sig;
242  std::string message = "Floating-point exception (FPE).";
243 
244  if (sinfo) {
245  switch (sinfo->si_code) {
246 #ifdef FPE_NOOP /* BUG: MacOSX uses this instead of INTDIV */
247  case FPE_NOOP:
248 #endif
249  case FPE_INTDIV:
250  message = "Integer divide by zero.";
251  break;
252  case FPE_INTOVF:
253  message = "Integer overflow.";
254  break;
255  case FPE_FLTDIV:
256  message = "Floating point divide by zero.";
257  break;
258  case FPE_FLTOVF:
259  message = "Floating point overflow.";
260  break;
261  case FPE_FLTUND:
262  message = "Floating point underflow.";
263  break;
264  case FPE_FLTRES:
265  message = "Floating point inexact result.";
266  break;
267  case FPE_FLTINV:
268  message = "Floating point invalid operation.";
269  break;
270  case FPE_FLTSUB:
271  message = "Subscript out of range.";
272  break;
273  default:
274  message = "Unknown error.";
275  break;
276  }
277  }
278 
279  std::cerr << " - " << message << std::endl;
280 
281  ::abort();
282  }
283 
284  static void InvalidOperationDetection()
285  {
286  struct sigaction termaction, oldaction;
287 
288  std::cout << std::endl
289  << " "
290  << "############################################" << std::endl
291  << " "
292  << "!!! WARNING - FPE detection is activated !!!" << std::endl
293  << " "
294  << "############################################" << std::endl;
295 
296  feenableexcept ( FE_DIVBYZERO );
297  feenableexcept ( FE_INVALID );
298  // fedisableexcept( FE_OVERFLOW );
299  // fedisableexcept( FE_UNDERFLOW );
300 
301  sigfillset(&termaction.sa_mask);
302  sigdelset(&termaction.sa_mask,SIGFPE);
303  termaction.sa_sigaction=TerminationSignalHandler;
304  termaction.sa_flags=SA_SIGINFO;
305  sigaction(SIGFPE, &termaction, &oldaction);
306  }
307 #else /* Not Linux, nor MacOSX ... */
308 
309  static void InvalidOperationDetection() {;}
310 
311 #endif /* Linus or MacOSX */
312 #else /* Not GCC */
313 
314  static void InvalidOperationDetection() {;}
315 #endif
316 #endif /* G4FPEDetection_h */
#define buffer
Definition: xmlparse.cc:611
static void InvalidOperationDetection()