/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see .
Class
Foam::sigFpe
Description
Set up trapping for floating point exceptions (signal FPE).
Defined by controlDict InfoSwitch entries:
- \par trapFpe
Enable floating point exception trapping.
- \par setNaN
Initialization all malloced memory to NaN.
Combined with \c trapFpe, this causes usage of uninitialized scalars
to trigger an abort.
Environment variables:
- \par FOAM_SIGFPE (true|false)
overrides \c trapFpe
- \par FOAM_SETNAN (true|false)
overrides \c setNaN
Note that trapping can be set/removed through the static member functions
or through the scope of the object (constructor sets trapping; destructor
restores original). The class behaves as a singleton.
SourceFiles
sigFpe.cxx
\*---------------------------------------------------------------------------*/
#ifndef Foam_sigFpe_H
#define Foam_sigFpe_H
#include
#include
#include // For std::size_t
#include "scalarFwd.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward Declarations
template class UList;
/*---------------------------------------------------------------------------*\
Class sigFpe Declaration
\*---------------------------------------------------------------------------*/
class sigFpe
{
// Private Data
//- Flag that floating point trapping should be used.
// Can override with FOAM_SIGFPE env variable
static bool switchFpe_;
//- Flag that NaN initialisation should be used.
// Can override with FOAM_SETNAN env variable
static bool switchNan_;
//- Floating point trapping currently active?
static bool sigActive_;
//- Is NaN memory initialisation currently active?
static bool nanActive_;
// Private Member Functions
//- Handler for caught signals - ends job and prints stack
static void sigHandler(int);
//- Fill (float | double) buffer with signalling NaN
template
inline static void fill_with_NaN(FloatType* buf, size_t count)
{
if (buf && count)
{
const auto val =
std::numeric_limits::signaling_NaN();
// [float|double] so do not need std::uninitialized_fill_n()
// Can dispatch with
// - std::execution::par_unseq
// - std::execution::unseq
std::fill_n(buf, count, val);
}
}
public:
// Constructors
//- Constructor calls set() to activate the FPE signal handler if it
//- was was not previously activate and requested() returns true.
sigFpe();
//- Destructor calls unset() to deactivate the FPE signal handler
//- as required.
~sigFpe();
// Static Member Functions
//- Check if SIGFPE signals handler is to be enabled.
// This is controlled by the trapFpe entry or the FOAM_SIGFPE
// environment variable
static bool requested();
//- True if SIGFPE handling is currently active.
static bool active() noexcept { return sigActive_; }
//- True if NaN memory initialisation is currently active.
static bool nanActive() noexcept { return nanActive_; }
//- Set NaN memory initialisation on/off.
// \return the previous value
static bool nanActive(bool on) noexcept
{
bool old(nanActive_);
nanActive_ = on;
return old;
}
//- Activate SIGFPE handler when FOAM_SIGFPE is enabled.
//- Activate fill memory with signaling_NaN when FOAM_SETNAN is enabled
static void set(bool verbose=false);
//- Deactivate SIGFPE handler and NaN memory initialisation
static void unset(bool verbose=false);
//- Fill data block with signaling_NaN values if nanActive().
//- Does a reinterpret to \c Foam::scalar
static void fillNan_if(void* buf, size_t count)
{
if (nanActive_)
{
fill_with_NaN
(
reinterpret_cast(buf),
(count/sizeof(Foam::scalar))
);
}
}
//- Fill data block with signaling_NaN values.
//- Does a reinterpret to \c Foam::scalar
static void fillNan(char* buf, size_t count)
{
fill_with_NaN
(
reinterpret_cast(buf),
(count/sizeof(Foam::scalar))
);
}
//- Fill data block with (float) signaling_NaN values
static void fillNan(UList& list);
//- Fill data block with (double) signaling_NaN values
static void fillNan(UList& list);
// Helpers
//- Helper to locally ignore SIGFPE handling.
// Restores the original state of the SIGFPE handler on destruction.
class ignore
{
//- The signal handler state when entering
bool wasActive_;
public:
//- No copy construct
ignore(const ignore&) = delete;
//- No move construct
ignore(ignore&&) = delete;
//- No copy assignment
void operator=(const ignore&) = delete;
//- No move assignment
void operator=(ignore&&) = delete;
//- Constructor deactivates any previously active SIGFPE handler
ignore()
:
wasActive_(Foam::sigFpe::active())
{
if (wasActive_)
{
Foam::sigFpe::unset();
}
}
//- Destructor restores the original state of SIGFPE handler
~ignore() { reset(); }
//- Restore the original state of SIGFPE handler
void reset()
{
if (wasActive_)
{
wasActive_ = false;
Foam::sigFpe::set();
}
}
//- Same as reset()
void restore() { reset(); }
};
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //