sigFpe.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "sigFpe.H"
27 #include "error.H"
28 #include "JobInfo.H"
29 #include "OSspecific.H"
30 #include "IOstreams.H"
31 
32 #ifdef LINUX_GNUC
33  #ifndef __USE_GNU
34  #define __USE_GNU
35  #endif
36  #include <fenv.h>
37  #include <malloc.h>
38 #elif defined(sgiN32) || defined(sgiN32Gcc)
39  #include <sigfpe.h>
40 #endif
41 
42 #include <limits>
43 
44 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
45 
46 struct sigaction Foam::sigFpe::oldAction_;
47 
48 void Foam::sigFpe::fillNan(UList<scalar>& lst)
49 {
50  lst = std::numeric_limits<scalar>::signaling_NaN();
51 }
52 
54 
55 
56 #ifdef LINUX
57 extern "C"
58 {
59  extern void* __libc_malloc(size_t size);
60 
61  // Override the GLIBC malloc to support mallocNan
62  void* malloc(size_t size)
63  {
65  {
66  return Foam::sigFpe::mallocNan(size);
67  }
68  else
69  {
70  return __libc_malloc(size);
71  }
72  }
73 }
74 
75 void* Foam::sigFpe::mallocNan(size_t size)
76 {
77  // Call the low-level GLIBC malloc function
78  void * result = __libc_malloc(size);
79 
80  // Initialize to signalling NaN
81  UList<scalar> lst(reinterpret_cast<scalar*>(result), size/sizeof(scalar));
82  sigFpe::fillNan(lst);
83 
84  return result;
85 }
86 #endif
87 
88 
89 #ifdef LINUX_GNUC
90 void Foam::sigFpe::sigHandler(int)
91 {
92  // Reset old handling
93  if (sigaction(SIGFPE, &oldAction_, NULL) < 0)
94  {
96  (
97  "Foam::sigSegv::sigHandler()"
98  ) << "Cannot reset SIGFPE trapping"
99  << abort(FatalError);
100  }
101 
102  // Update jobInfo file
103  jobInfo.signalEnd();
104 
105  error::printStack(Perr);
106 
107  // Throw signal (to old handler)
108  raise(SIGFPE);
109 }
110 #endif
111 
112 
113 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
114 
116 {
117  oldAction_.sa_handler = NULL;
118 }
119 
120 
121 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
122 
124 {
125  if (env("FOAM_SIGFPE"))
126  {
127  #ifdef LINUX_GNUC
128  // Reset signal
129  if (oldAction_.sa_handler && sigaction(SIGFPE, &oldAction_, NULL) < 0)
130  {
132  (
133  "Foam::sigFpe::~sigFpe()"
134  ) << "Cannot reset SIGFPE trapping"
135  << abort(FatalError);
136  }
137  #endif
138  }
139 
140  if (env("FOAM_SETNAN"))
141  {
142  #ifdef LINUX
143  // Disable initialization to NaN
144  mallocNanActive_ = false;
145  #endif
146  }
147 }
148 
149 
150 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
151 
152 void Foam::sigFpe::set(const bool verbose)
153 {
154  if (oldAction_.sa_handler)
155  {
157  (
158  "Foam::sigFpe::set()"
159  ) << "Cannot call sigFpe::set() more than once"
160  << abort(FatalError);
161  }
162 
163  if (env("FOAM_SIGFPE"))
164  {
165  bool supported = false;
166 
167  #ifdef LINUX_GNUC
168  supported = true;
169 
170  feenableexcept
171  (
172  FE_DIVBYZERO
173  | FE_INVALID
174  | FE_OVERFLOW
175  );
176 
177  struct sigaction newAction;
178  newAction.sa_handler = sigHandler;
179  newAction.sa_flags = SA_NODEFER;
180  sigemptyset(&newAction.sa_mask);
181  if (sigaction(SIGFPE, &newAction, &oldAction_) < 0)
182  {
184  (
185  "Foam::sigFpe::set()"
186  ) << "Cannot set SIGFPE trapping"
187  << abort(FatalError);
188  }
189 
190 
191  #elif defined(sgiN32) || defined(sgiN32Gcc)
192  supported = true;
193 
194  sigfpe_[_DIVZERO].abort=1;
195  sigfpe_[_OVERFL].abort=1;
196  sigfpe_[_INVALID].abort=1;
197 
198  sigfpe_[_DIVZERO].trace=1;
199  sigfpe_[_OVERFL].trace=1;
200  sigfpe_[_INVALID].trace=1;
201 
202  handle_sigfpes
203  (
204  _ON,
205  _EN_DIVZERO
206  | _EN_INVALID
207  | _EN_OVERFL,
208  0,
209  _ABORT_ON_ERROR,
210  NULL
211  );
212  #endif
213 
214 
215  if (verbose)
216  {
217  if (supported)
218  {
219  Info<< "sigFpe : Enabling floating point exception trapping"
220  << " (FOAM_SIGFPE)." << endl;
221  }
222  else
223  {
224  Info<< "sigFpe : Floating point exception trapping"
225  << " - not supported on this platform" << endl;
226  }
227  }
228  }
229 
230 
231  if (env("FOAM_SETNAN"))
232  {
233  #ifdef LINUX
234  mallocNanActive_ = true;
235  #endif
236 
237  if (verbose)
238  {
239  if (mallocNanActive_)
240  {
241  Info<< "SetNaN : Initialising allocated memory to NaN"
242  << " (FOAM_SETNAN)." << endl;
243  }
244  else
245  {
246  Info<< "SetNaN : Initialise allocated memory to NaN"
247  << " - not supported on this platform" << endl;
248  }
249  }
250  }
251 }
252 
253 
254 // ************************************************************************* //
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
prefixOSstream Perr(cerr,"Perr")
Definition: IOstreams.H:54
messageStream Info
void set(const bool verbose)
Activate SIGFPE signal handler when FOAM_SIGFPE is set.
Definition: sigFpe.C:152
void signalEnd() const
Definition: JobInfo.C:176
Namespace for OpenFOAM.
Useful combination of include files which define Sin, Sout and Serr and the use of IO streams general...
~sigFpe()
Destructor.
Definition: sigFpe.C:123
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
static void fillNan(UList< scalar > &)
Fill block of data with NaN.
Definition: sigFpe.C:48
errorManip< error > abort(error &err)
Definition: errorManip.H:131
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:314
JobInfo jobInfo
Definition: JobInfo.C:35
static bool mallocNanActive_
Flag to indicate mallocNan is enabled.
Definition: sigFpe.H:103
error FatalError
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:60
bool env(const word &)
Return true if environment variable of given name is defined.
Definition: POSIX.C:96
sigFpe()
Construct null.
Definition: sigFpe.C:115