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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2015 OpenFOAM Foundation
9  Copyright (C) 2011 Symscape
10  Copyright (C) 2016-2018 OpenCFD Ltd.
11 -------------------------------------------------------------------------------
12 License
13  This file is part of OpenFOAM.
14 
15  OpenFOAM is free software: you can redistribute it and/or modify it
16  under the terms of the GNU General Public License as published by
17  the Free Software Foundation, either version 3 of the License, or
18  (at your option) any later version.
19 
20  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
21  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23  for more details.
24 
25  You should have received a copy of the GNU General Public License
26  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
27 
28 \*---------------------------------------------------------------------------*/
29 
30 #include "sigFpe.H"
31 #include "error.H"
32 #include "JobInfo.H"
33 #include "OSspecific.H"
34 #include "IOstreams.H"
35 #include "Switch.H"
36 #include "UList.H"
37 
38 #include <float.h> // For *fp functions
39 #include <limits>
40 
41 // File-local functions
42 #include "signalMacros.C"
43 
44 
45 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
46 
47 bool Foam::sigFpe::switchFpe_(Foam::debug::optimisationSwitch("trapFpe", 0));
48 bool Foam::sigFpe::switchNan_(Foam::debug::optimisationSwitch("setNaN", 0));
49 
50 bool Foam::sigFpe::sigActive_ = false;
51 bool Foam::sigFpe::nanActive_ = false;
52 
53 // Saved old FPE signal trapping setting (file-local variable)
54 static unsigned int oldFpe_ = 0u;
55 
56 
57 static void clearFpe()
58 {
59  #ifndef Foam_no_sigFpe
60  _clearfp();
61  _controlfp(oldFpe_, 0xFFFFFFFF);
62  #endif
63 }
64 
65 
66 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
67 
68 // Can turn on/off via env variable containing a bool (true|false|on|off ...)
69 // or by the specified flag
70 static bool isTrue(const char* envName, bool deflt)
71 {
72  const auto str(Foam::getEnv(envName));
73 
74  if (str.size())
75  {
76  Foam::Switch sw(str, true); // Silently ignores bad input
77 
78  if (sw.valid())
79  {
80  return sw;
81  }
82  }
83 
84  // Env was not set or did not contain a valid bool value
85  return deflt;
86 }
87 
88 
89 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
90 
91 void Foam::sigFpe::sigHandler(int)
92 {
93  resetHandler("SIGFPE", SIGFPE);
94 
95  jobInfo.signalEnd(); // Update jobInfo file
97  clearFpe();
98  ::raise(SIGFPE); // Throw signal (to old handler)
99 }
100 
101 
102 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
103 
105 {
106  set(false);
107 }
108 
109 
111 :
112  wasActive_(sigFpe::active())
113 {
114  if (wasActive_)
115  {
116  sigFpe::unset();
117  }
118 }
119 
120 
121 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
122 
124 {
125  unset(false);
126 }
127 
128 
130 {
131  restore();
132 }
133 
134 
135 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
136 
138 {
139  if (wasActive_)
140  {
141  sigFpe::set();
142  }
143  wasActive_ = false;
144 }
145 
146 
148 {
149  return isTrue("FOAM_SIGFPE", switchFpe_);
150 }
151 
152 
153 void Foam::sigFpe::set(bool verbose)
154 {
155  if (!sigActive_ && requested())
156  {
157  #ifdef Foam_no_sigFpe
158 
159  if (verbose)
160  {
161  Info<< "trapFpe: Floating point exception trapping ";
162  Info<< "- disabled on this platform" << endl;
163  }
164 
165  #else
166 
167  oldFpe_ = _controlfp(0, 0);
168 
169  const unsigned int newFpe =
170  (
171  oldFpe_ & ~(_EM_ZERODIVIDE | _EM_INVALID | _EM_OVERFLOW)
172  );
173 
174  _controlfp(newFpe, _MCW_EM);
175 
176  setHandler("SIGFPE", SIGFPE, sigHandler);
177 
178  sigActive_ = true;
179 
180  if (verbose)
181  {
182  Info<< "trapFpe: Floating point exception trapping ";
183 
184  if (sigActive_)
185  {
186  Info<< "enabled (FOAM_SIGFPE)." << endl;
187  }
188  else
189  {
190  Info<< "- not supported on this platform" << endl;
191  }
192  }
193  #endif
194  }
195 
196 
197  nanActive_ = false;
198  if (isTrue("FOAM_SETNAN", switchNan_))
199  {
200  if (verbose)
201  {
202  Info<< "setNaN : Initialise allocated memory to NaN "
203  << "- not supported on this platform" << endl;
204  }
205  }
206 }
207 
208 
209 void Foam::sigFpe::unset(bool verbose)
210 {
211  if (sigActive_)
212  {
213  if (verbose)
214  {
215  Info<< "sigFpe : Disabling floating point exception trapping"
216  << endl;
217  }
218 
219  sigActive_ = false;
220 
221  clearFpe();
222 
223  resetHandler("SIGFPE", SIGFPE);
224  }
225 
226  nanActive_ = false;
227 }
228 
229 
231 {
232  list = std::numeric_limits<scalar>::signaling_NaN();
233 }
234 
235 
236 // ************************************************************************* //
Foam::sigFpe::set
static void set(bool verbose=false)
Activate SIGFPE signal handler when FOAM_SIGFPE is set.
Definition: sigFpe.C:153
OSspecific.H
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
Foam::Switch
A simple wrapper around bool so that it can be read as a word: true/false, on/off,...
Definition: Switch.H:70
Foam::error::printStack
static void printStack(Ostream &os)
Helper function to print a stack.
Definition: dummyPrintStack.C:36
IOstreams.H
Useful combination of include files which define Sin, Sout and Serr and the use of IO streams general...
Foam::resetHandler
static void resetHandler(const char *what, int sigNum)
Definition: signalMacros.C:46
Foam::sigFpe::ignore::ignore
ignore()
Constructor deactivates any previously active SIGFPE handler.
Definition: sigFpe.C:110
Foam::Switch::valid
bool valid() const noexcept
True if the Switch represents a valid enumeration.
Definition: Switch.C:203
Foam::sigFpe::unset
static void unset(bool verbose=false)
Deactivate SIGFPE signal handler and NaN memory initialisation.
Definition: sigFpe.C:209
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
clearFpe
static void clearFpe()
Definition: sigFpe.C:57
sigFpe.H
Foam::getEnv
string getEnv(const std::string &envName)
Get environment value for given envName.
Definition: MSwindows.C:371
error.H
Foam::sigFpe::fillNan
static void fillNan(UList< scalar > &list)
Fill data block with NaN values.
Definition: sigFpe.C:230
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Switch.H
Foam::sigFpe::ignore::~ignore
~ignore()
Destructor restores the original state of SIGFPE handler.
Definition: sigFpe.C:129
signalMacros.C
File-local code for setting/resetting signal handlers.
Foam::debug::optimisationSwitch
int optimisationSwitch(const char *name, const int deflt=0)
Lookup optimisation switch or add default value.
Definition: debug.C:237
Foam::sigFpe
Set up trapping for floating point exceptions (signal FPE).
Definition: sigFpe.H:73
Foam::sigFpe::requested
static bool requested()
Check if SIGFPE signals handler is to be enabled.
Definition: sigFpe.C:147
Foam::jobInfo
JobInfo jobInfo
Definition: JobInfo.C:49
Foam::Perr
prefixOSstream Perr
An Ostream wrapper for parallel output to std::cerr.
Foam::setHandler
static void setHandler(const char *what, int sigNum, void(*handler)(int))
Definition: signalMacros.C:61
UList.H
Foam::sigFpe::ignore::restore
void restore()
Restore the original state of SIGFPE handler.
Definition: sigFpe.C:137
oldFpe_
static unsigned int oldFpe_
Definition: sigFpe.C:54
Foam::UList
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:103
JobInfo.H
Foam::JobInfo::signalEnd
void signalEnd() const
Update job info and relocate the file from running to finished.
Definition: JobInfo.C:184
Foam::sigFpe::sigFpe
sigFpe()
Definition: sigFpe.C:104
isTrue
static bool isTrue(const char *envName, bool deflt)
Definition: sigFpe.C:70
Foam::sigFpe::~sigFpe
~sigFpe()
Definition: sigFpe.C:123