sigFpe.H
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-2016 OpenFOAM Foundation
9  Copyright (C) 2018-2025 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 Class
28  Foam::sigFpe
29 
30 Description
31  Set up trapping for floating point exceptions (signal FPE).
32 
33  Defined by controlDict InfoSwitch entries:
34  - \par trapFpe
35  Enable floating point exception trapping.
36 
37  - \par setNaN
38  Initialization all malloced memory to NaN.
39  Combined with \c trapFpe, this causes usage of uninitialized scalars
40  to trigger an abort.
41 
42  Environment variables:
43  - \par FOAM_SIGFPE (true|false)
44  overrides \c trapFpe
45  - \par FOAM_SETNAN (true|false)
46  overrides \c setNaN
47 
48  Note that trapping can be set/removed through the static member functions
49  or through the scope of the object (constructor sets trapping; destructor
50  restores original). The class behaves as a singleton.
51 
52 SourceFiles
53  sigFpe.cxx
54 
55 \*---------------------------------------------------------------------------*/
56 
57 #ifndef Foam_sigFpe_H
58 #define Foam_sigFpe_H
59 
60 #include <algorithm>
61 #include <limits>
62 #include <cstddef> // For std::size_t
63 #include "scalarFwd.H"
64 
65 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
66 
67 namespace Foam
68 {
69 
70 // Forward Declarations
71 template<class T> class UList;
72 
73 /*---------------------------------------------------------------------------*\
74  Class sigFpe Declaration
75 \*---------------------------------------------------------------------------*/
76 
77 class sigFpe
78 {
79  // Private Data
80 
81  //- Flag that floating point trapping should be used.
82  // Can override with FOAM_SIGFPE env variable
83  static bool switchFpe_;
84 
85  //- Flag that NaN initialisation should be used.
86  // Can override with FOAM_SETNAN env variable
87  static bool switchNan_;
88 
89  //- Floating point trapping currently active?
90  static bool sigActive_;
91 
92  //- Is NaN memory initialisation currently active?
93  static bool nanActive_;
94 
95 
96  // Private Member Functions
97 
98  //- Handler for caught signals - ends job and prints stack
99  static void sigHandler(int);
100 
101  //- Fill (float | double) buffer with signalling NaN
102  template<class FloatType>
103  inline static void fill_with_NaN(FloatType* buf, size_t count)
104  {
105  if (buf && count)
106  {
107  const auto val =
108  std::numeric_limits<FloatType>::signaling_NaN();
109 
110  // [float|double] so do not need std::uninitialized_fill_n()
111  // Can dispatch with
112  // - std::execution::par_unseq
113  // - std::execution::unseq
114  std::fill_n(buf, count, val);
115  }
116  }
117 
118 
119 public:
120 
121  // Constructors
122 
123  //- Constructor calls set() to activate the FPE signal handler if it
124  //- was was not previously activate and requested() returns true.
125  sigFpe();
126 
127 
128  //- Destructor calls unset() to deactivate the FPE signal handler
129  //- as required.
130  ~sigFpe();
131 
132 
133  // Static Member Functions
134 
135  //- Check if SIGFPE signals handler is to be enabled.
136  // This is controlled by the trapFpe entry or the FOAM_SIGFPE
137  // environment variable
138  static bool requested();
139 
140  //- True if SIGFPE handling is currently active.
141  static bool active() noexcept { return sigActive_; }
142 
143  //- True if NaN memory initialisation is currently active.
144  static bool nanActive() noexcept { return nanActive_; }
145 
146  //- Set NaN memory initialisation on/off.
147  // \return the previous value
148  static bool nanActive(bool on) noexcept
149  {
150  bool old(nanActive_);
151  nanActive_ = on;
152  return old;
153  }
154 
155  //- Activate SIGFPE handler when FOAM_SIGFPE is enabled.
156  //- Activate fill memory with signaling_NaN when FOAM_SETNAN is enabled
157  static void set(bool verbose=false);
158 
159  //- Deactivate SIGFPE handler and NaN memory initialisation
160  static void unset(bool verbose=false);
161 
162  //- Fill data block with signaling_NaN values if nanActive().
163  //- Does a reinterpret to \c Foam::scalar
164  static void fillNan_if(void* buf, size_t count)
165  {
166  if (nanActive_)
167  {
168  fill_with_NaN
169  (
170  reinterpret_cast<Foam::scalar*>(buf),
171  (count/sizeof(Foam::scalar))
172  );
173  }
174  }
175 
176  //- Fill data block with signaling_NaN values.
177  //- Does a reinterpret to \c Foam::scalar
178  static void fillNan(char* buf, size_t count)
179  {
180  fill_with_NaN
181  (
182  reinterpret_cast<Foam::scalar*>(buf),
183  (count/sizeof(Foam::scalar))
184  );
185  }
186 
187  //- Fill data block with (float) signaling_NaN values
188  static void fillNan(UList<float>& list);
189 
190  //- Fill data block with (double) signaling_NaN values
191  static void fillNan(UList<double>& list);
192 
194  // Helpers
195 
196  //- Helper to locally ignore SIGFPE handling.
197  // Restores the original state of the SIGFPE handler on destruction.
198  class ignore
199  {
200  //- The signal handler state when entering
201  bool wasActive_;
202 
203  public:
204 
205  //- No copy construct
206  ignore(const ignore&) = delete;
207 
208  //- No move construct
209  ignore(ignore&&) = delete;
210 
211  //- No copy assignment
212  void operator=(const ignore&) = delete;
213 
214  //- No move assignment
215  void operator=(ignore&&) = delete;
216 
217  //- Constructor deactivates any previously active SIGFPE handler
218  ignore()
219  :
220  wasActive_(Foam::sigFpe::active())
221  {
222  if (wasActive_)
223  {
225  }
226  }
227 
228  //- Destructor restores the original state of SIGFPE handler
229  ~ignore() { reset(); }
230 
231  //- Restore the original state of SIGFPE handler
232  void reset()
233  {
234  if (wasActive_)
235  {
236  wasActive_ = false;
238  }
239  }
240 
241  //- Same as reset()
242  void restore() { reset(); }
243  };
244 };
245 
246 
247 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
248 
249 } // End namespace Foam
250 
251 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
252 
253 #endif
254 
255 // ************************************************************************* //
static void set(bool verbose=false)
Activate SIGFPE handler when FOAM_SIGFPE is enabled. Activate fill memory with signaling_NaN when FOA...
static void fillNan(char *buf, size_t count)
Fill data block with signaling_NaN values. Does a reinterpret to Foam::scalar.
Definition: sigFpe.H:209
static bool active() noexcept
True if SIGFPE handling is currently active.
Definition: sigFpe.H:159
static void fillNan_if(void *buf, size_t count)
Fill data block with signaling_NaN values if nanActive(). Does a reinterpret to Foam::scalar.
Definition: sigFpe.H:193
static bool requested()
Check if SIGFPE signals handler is to be enabled.
ignore()
Constructor deactivates any previously active SIGFPE handler.
Definition: sigFpe.H:268
~sigFpe()
Destructor calls unset() to deactivate the FPE signal handler as required.
static void unset(bool verbose=false)
Deactivate SIGFPE handler and NaN memory initialisation.
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of &#39;true&#39; entries.
Definition: BitOps.H:73
Set up trapping for floating point exceptions (signal FPE).
Definition: sigFpe.H:72
~ignore()
Destructor restores the original state of SIGFPE handler.
Definition: sigFpe.H:281
Helper to locally ignore SIGFPE handling.
Definition: sigFpe.H:236
const direction noexcept
Definition: scalarImpl.H:255
static bool nanActive() noexcept
True if NaN memory initialisation is currently active.
Definition: sigFpe.H:164
Typedefs for float/double/scalar without requiring scalar.H.
void operator=(const ignore &)=delete
No copy assignment.
void reset()
Restore the original state of SIGFPE handler.
Definition: sigFpe.H:286
sigFpe()
Constructor calls set() to activate the FPE signal handler if it was was not previously activate and ...
void restore()
Same as reset()
Definition: sigFpe.H:298
Namespace for OpenFOAM.