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  << "Cannot reset SIGFPE trapping"
97  << abort(FatalError);
98  }
99 
100  // Update jobInfo file
101  jobInfo.signalEnd();
102 
103  error::printStack(Perr);
104 
105  // Throw signal (to old handler)
106  raise(SIGFPE);
107 }
108 #endif
109 
110 
111 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
112 
114 {
115  oldAction_.sa_handler = NULL;
116 }
117 
118 
119 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
120 
122 {
123  if (env("FOAM_SIGFPE"))
124  {
125  #ifdef LINUX_GNUC
126  // Reset signal
127  if (oldAction_.sa_handler && sigaction(SIGFPE, &oldAction_, NULL) < 0)
128  {
130  << "Cannot reset SIGFPE trapping"
131  << abort(FatalError);
132  }
133  #endif
134  }
135 
136  if (env("FOAM_SETNAN"))
137  {
138  #ifdef LINUX
139  // Disable initialization to NaN
140  mallocNanActive_ = false;
141  #endif
142  }
143 }
144 
145 
146 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
147 
148 void Foam::sigFpe::set(const bool verbose)
149 {
150  if (oldAction_.sa_handler)
151  {
153  << "Cannot call sigFpe::set() more than once"
154  << abort(FatalError);
155  }
156 
157  if (env("FOAM_SIGFPE"))
158  {
159  bool supported = false;
160 
161  #ifdef LINUX_GNUC
162  supported = true;
163 
164  feenableexcept
165  (
166  FE_DIVBYZERO
167  | FE_INVALID
168  | FE_OVERFLOW
169  );
170 
171  struct sigaction newAction;
172  newAction.sa_handler = sigHandler;
173  newAction.sa_flags = SA_NODEFER;
174  sigemptyset(&newAction.sa_mask);
175  if (sigaction(SIGFPE, &newAction, &oldAction_) < 0)
176  {
178  << "Cannot set SIGFPE trapping"
179  << abort(FatalError);
180  }
181 
182 
183  #elif defined(sgiN32) || defined(sgiN32Gcc)
184  supported = true;
185 
186  sigfpe_[_DIVZERO].abort=1;
187  sigfpe_[_OVERFL].abort=1;
188  sigfpe_[_INVALID].abort=1;
189 
190  sigfpe_[_DIVZERO].trace=1;
191  sigfpe_[_OVERFL].trace=1;
192  sigfpe_[_INVALID].trace=1;
193 
194  handle_sigfpes
195  (
196  _ON,
197  _EN_DIVZERO
198  | _EN_INVALID
199  | _EN_OVERFL,
200  0,
201  _ABORT_ON_ERROR,
202  NULL
203  );
204  #endif
205 
206 
207  if (verbose)
208  {
209  if (supported)
210  {
211  Info<< "sigFpe : Enabling floating point exception trapping"
212  << " (FOAM_SIGFPE)." << endl;
213  }
214  else
215  {
216  Info<< "sigFpe : Floating point exception trapping"
217  << " - not supported on this platform" << endl;
218  }
219  }
220  }
221 
222 
223  if (env("FOAM_SETNAN"))
224  {
225  #ifdef LINUX
226  mallocNanActive_ = true;
227  #endif
228 
229  if (verbose)
230  {
231  if (mallocNanActive_)
232  {
233  Info<< "SetNaN : Initialising allocated memory to NaN"
234  << " (FOAM_SETNAN)." << endl;
235  }
236  else
237  {
238  Info<< "SetNaN : Initialise allocated memory to NaN"
239  << " - not supported on this platform" << endl;
240  }
241  }
242  }
243 }
244 
245 
246 // ************************************************************************* //
error FatalError
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:253
~sigFpe()
Destructor.
Definition: sigFpe.C:121
Useful combination of include files which define Sin, Sout and Serr and the use of IO streams general...
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
static void fillNan(UList< scalar > &)
Fill block of data with NaN.
Definition: sigFpe.C:48
errorManip< error > abort(error &err)
Definition: errorManip.H:131
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
prefixOSstream Perr(cerr,"Perr")
Definition: IOstreams.H:54
void signalEnd() const
Definition: JobInfo.C:175
JobInfo jobInfo
Definition: JobInfo.C:35
void set(const bool verbose)
Activate SIGFPE signal handler when FOAM_SIGFPE is set.
Definition: sigFpe.C:148
messageStream Info
static bool mallocNanActive_
Flag to indicate mallocNan is enabled.
Definition: sigFpe.H:103
bool env(const word &)
Return true if environment variable of given name is defined.
Definition: POSIX.C:96
sigFpe()
Construct null.
Definition: sigFpe.C:113
Namespace for OpenFOAM.