ENH: add trapFpe and setNaN optimisationSwitch (issue #517)

- allows configuration without an environment variable.
  For compatibility still respect FOAM_SIGFPE and FOAM_SETNAN
  env-variables

- The env-variables are now treated as true/false switch values.
  Previously there was just a check for env exists or not, but this
  can be fairly fragile for a user's environment.
This commit is contained in:
Mark Olesen
2017-07-05 17:49:37 +02:00
parent e54a930dcc
commit c50368ecc6
14 changed files with 139 additions and 83 deletions

View File

@ -59,6 +59,7 @@ Usage
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "argList.H" #include "argList.H"
#include "sigFpe.H"
#include "Time.H" #include "Time.H"
#include "fvMesh.H" #include "fvMesh.H"
#include "fvMeshTools.H" #include "fvMeshTools.H"
@ -2277,7 +2278,7 @@ int main(int argc, char *argv[])
bool newTimes = args.optionFound("newTimes"); bool newTimes = args.optionFound("newTimes");
if (env("FOAM_SIGFPE")) if (Foam::sigFpe::requested())
{ {
WarningInFunction WarningInFunction
<< "Detected floating point exception trapping (FOAM_SIGFPE)." << "Detected floating point exception trapping (FOAM_SIGFPE)."
@ -2287,7 +2288,6 @@ int main(int argc, char *argv[])
} }
const HashSet<word> selectedFields(0); const HashSet<word> selectedFields(0);
const HashSet<word> selectedLagrangianFields(0); const HashSet<word> selectedLagrangianFields(0);

View File

@ -39,8 +39,9 @@ usage: ${0##*/}
-foamVersion ver specify project version (eg, 1612) -foamVersion ver specify project version (eg, 1612)
-projectName name specify project directory name (eg, openfoam1612) -projectName name specify project directory name (eg, openfoam1612)
-archOption 32|64 specify 'WM_ARCH_OPTION' architecture option -archOption 32|64 specify 'WM_ARCH_OPTION' architecture option
-SP | -float32 specify 'WM_PRECISION_OPTION'
-DP | -float64 specify 'WM_PRECISION_OPTION'
-int32 | -int64 specify 'WM_LABEL_SIZE' -int32 | -int64 specify 'WM_LABEL_SIZE'
-SP | -DP specify 'WM_PRECISION_OPTION'
-system name specify 'system' compiler to be used -system name specify 'system' compiler to be used
-third name specify 'ThirdParty' compiler to be used -third name specify 'ThirdParty' compiler to be used
-boost ver specify 'boost_version' -boost ver specify 'boost_version'
@ -63,7 +64,7 @@ usage: ${0##*/}
-scotch-path dir specify 'SCOTCH_ARCH_PATH' (eg, /opt/OpenFOAM-scotch_6.0.4) -scotch-path dir specify 'SCOTCH_ARCH_PATH' (eg, /opt/OpenFOAM-scotch_6.0.4)
-vtk ver specify 'vtk_version' (eg, VTK-7.1.0) -vtk ver specify 'vtk_version' (eg, VTK-7.1.0)
-mesa ver specify 'mesa_version' (eg, mesa-13.0.1) -mesa ver specify 'mesa_version' (eg, mesa-13.0.1)
-sigfpe | -no-sigfpe activate/deactivate FOAM_SIGFPE handling -sigfpe | -no-sigfpe [defunct - now under etc/controlDict]
gmp-VERSION for ThirdParty gcc (gmp-system for system library) gmp-VERSION for ThirdParty gcc (gmp-system for system library)
mpfr-VERSION for ThirdParty gcc (mpfr-system for system library) mpfr-VERSION for ThirdParty gcc (mpfr-system for system library)
mpc-VERSION for ThirdParty gcc (mpc-system for system library) mpc-VERSION for ThirdParty gcc (mpc-system for system library)
@ -251,6 +252,18 @@ do
shift shift
;; ;;
-SP | -float32)
# Replace WM_PRECISION_OPTION=...
replace etc/bashrc WM_PRECISION_OPTION "SP"
adjusted=true
;;
-DP | -float64)
# Replace WM_PRECISION_OPTION=...
replace etc/bashrc WM_PRECISION_OPTION "DP"
adjusted=true
;;
-int32 | -int64) -int32 | -int64)
# Replace WM_LABEL_SIZE=... # Replace WM_LABEL_SIZE=...
optionValue="${1#-int}" optionValue="${1#-int}"
@ -258,13 +271,6 @@ do
adjusted=true adjusted=true
;; ;;
-SP | -DP)
# Replace WM_PRECISION_OPTION=...
optionValue="${1#-}"
replace etc/bashrc WM_PRECISION_OPTION "$optionValue"
adjusted=true
;;
-system) -system)
# Replace WM_COMPILER_TYPE=... and WM_COMPILER=... # Replace WM_COMPILER_TYPE=... and WM_COMPILER=...
[ "$#" -ge 2 ] || die "'$1' option requires an argument" [ "$#" -ge 2 ] || die "'$1' option requires an argument"
@ -471,20 +477,8 @@ do
adjusted=true adjusted=true
;; ;;
-sigfpe) -sigfpe | -no-sigfpe)
# Enable FOAM_SIGFPE handling echo "Enable/disable FOAM_SIGFPE now via controlDict" 1>&2
_inlineSed etc/bashrc \
"[a-z][a-z]* FOAM_SIGFPE.*" \
"export FOAM_SIGFPE=" \
"Activate FOAM_SIGFPE handling"
;;
-no-sigfpe)
# Disable FOAM_SIGFPE handling
_inlineSed etc/bashrc \
"[a-z][a-z]* FOAM_SIGFPE.*" \
"unset FOAM_SIGFPE" \
"Deactivate FOAM_SIGFPE handling"
;; ;;
*) *)

View File

@ -96,13 +96,13 @@ export WM_MPLIB=SYSTEMOPENMPI
# WM_OSTYPE = POSIX # WM_OSTYPE = POSIX
#export WM_OSTYPE=POSIX #export WM_OSTYPE=POSIX
#- Floating-point signal handling: #- Alternative to 'trapFpe' controlDict entry
# set or unset # for floating-point exceptions (true|false)
export FOAM_SIGFPE= #export FOAM_SIGFPE=true
#- memory initialisation: #- Alternative to 'setNaN' controlDict entry
# set or unset # for memory initialisation (true|false)
#export FOAM_SETNAN= #export FOAM_SETNAN=false
################################################################################ ################################################################################

View File

@ -79,6 +79,14 @@ OptimisationSwitches
// global reduction, even if multi-pass is not needed) // global reduction, even if multi-pass is not needed)
maxCommsSize 0; maxCommsSize 0;
// Trap floating point exception.
// Can override with FOAM_SIGFPE (true|false)
trapFpe 1;
// Initialization malloced memory to NaN.
// Can override with FOAM_SETNAN (true|false)
setNaN 0;
// Force dumping (at next timestep) upon signal (-1 to disable) // Force dumping (at next timestep) upon signal (-1 to disable)
writeNowSignal -1; // 10; writeNowSignal -1; // 10;

View File

@ -93,13 +93,13 @@ setenv WM_MPLIB SYSTEMOPENMPI
# WM_OSTYPE = POSIX # WM_OSTYPE = POSIX
#setenv WM_OSTYPE POSIX #setenv WM_OSTYPE POSIX
#- Floating-point signal handling: #- Alternative to 'trapFpe' controlDict entry
# set or unset # for floating-point exceptions (true|false)
setenv FOAM_SIGFPE #setenv FOAM_SIGFPE true
#- memory initialisation: #- Alternative to 'setNaN' controlDict entry
# set or unset # for memory initialisation (true|false)
#setenv FOAM_SETNAN #setenv FOAM_SETNAN false
################################################################################ ################################################################################

View File

@ -28,6 +28,7 @@ License
#include "JobInfo.H" #include "JobInfo.H"
#include "OSspecific.H" #include "OSspecific.H"
#include "IOstreams.H" #include "IOstreams.H"
#include "Switch.H"
#ifdef LINUX_GNUC #ifdef LINUX_GNUC
#ifndef __USE_GNU #ifndef __USE_GNU
@ -43,17 +44,41 @@ License
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
bool Foam::sigFpe::switchFpe_(Foam::debug::optimisationSwitch("trapFpe", 0));
bool Foam::sigFpe::switchNan_(Foam::debug::optimisationSwitch("setNaN", 0));
bool Foam::sigFpe::sigActive_ = false;
bool Foam::sigFpe::mallocNanActive_ = false;
struct sigaction Foam::sigFpe::oldAction_; struct sigaction Foam::sigFpe::oldAction_;
bool Foam::sigFpe::sigFpeActive_ = false;
// File-scope function.
// Controlled by env variable containing a bool (true|false|on|off ...)
// or by the specified flag
static bool isTrue(const char* envName, const bool flag)
{
const std::string str = Foam::getEnv(envName);
if (str.size())
{
Foam::Switch sw(str, true); // silently ignore bad input
if (sw.valid())
{
return sw;
}
}
// Env was not set or did not contain a valid bool value
return flag;
}
void Foam::sigFpe::fillNan(UList<scalar>& lst) void Foam::sigFpe::fillNan(UList<scalar>& lst)
{ {
lst = std::numeric_limits<scalar>::signaling_NaN(); lst = std::numeric_limits<scalar>::signaling_NaN();
} }
bool Foam::sigFpe::mallocNanActive_ = false;
#ifdef LINUX #ifdef LINUX
extern "C" extern "C"
@ -128,9 +153,15 @@ Foam::sigFpe::~sigFpe()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::sigFpe::requested()
{
return isTrue("FOAM_SIGFPE", switchFpe_);
}
void Foam::sigFpe::set(const bool verbose) void Foam::sigFpe::set(const bool verbose)
{ {
if (!sigFpeActive_ && env("FOAM_SIGFPE")) if (!sigActive_ && requested())
{ {
bool supported = false; bool supported = false;
@ -155,7 +186,7 @@ void Foam::sigFpe::set(const bool verbose)
<< abort(FatalError); << abort(FatalError);
} }
sigFpeActive_ = true; sigActive_ = true;
#elif defined(sgiN32) || defined(sgiN32Gcc) #elif defined(sgiN32) || defined(sgiN32Gcc)
supported = true; supported = true;
@ -179,28 +210,28 @@ void Foam::sigFpe::set(const bool verbose)
nullptr nullptr
); );
sigFpeActive_ = true; sigActive_ = true;
#endif #endif
if (verbose) if (verbose)
{ {
Info<< "trapFpe: Floating point exception trapping ";
if (supported) if (supported)
{ {
Info<< "sigFpe : Enabling floating point exception trapping" Info<< "enabled (FOAM_SIGFPE)." << endl;
<< " (FOAM_SIGFPE)." << endl;
} }
else else
{ {
Info<< "sigFpe : Floating point exception trapping" Info<< "- not supported on this platform" << endl;
<< " - not supported on this platform" << endl;
} }
} }
} }
if (env("FOAM_SETNAN")) if (isTrue("FOAM_SETNAN", switchNan_))
{ {
#ifdef LINUX #ifdef LINUX
mallocNanActive_ = true; mallocNanActive_ = true;
@ -208,15 +239,15 @@ void Foam::sigFpe::set(const bool verbose)
if (verbose) if (verbose)
{ {
Info<< "setNaN : Initialise allocated memory to NaN ";
if (mallocNanActive_) if (mallocNanActive_)
{ {
Info<< "SetNaN : Initialising allocated memory to NaN" Info<< "enabled (FOAM_SETNAN)." << endl;
<< " (FOAM_SETNAN)." << endl;
} }
else else
{ {
Info<< "SetNaN : Initialise allocated memory to NaN" Info<< " - not supported on this platform" << endl;
<< " - not supported on this platform" << endl;
} }
} }
} }
@ -227,7 +258,7 @@ void Foam::sigFpe::unset(const bool verbose)
{ {
#ifdef LINUX_GNUC #ifdef LINUX_GNUC
// Reset signal // Reset signal
if (sigFpeActive_) if (sigActive_)
{ {
if (verbose) if (verbose)
{ {
@ -256,7 +287,7 @@ void Foam::sigFpe::unset(const bool verbose)
<< "Cannot reset SIGFPE trapping" << "Cannot reset SIGFPE trapping"
<< abort(FatalError); << abort(FatalError);
} }
sigFpeActive_ = false; sigActive_ = false;
} }
#endif #endif

View File

@ -27,17 +27,24 @@ Class
Description Description
Set up trapping for floating point exceptions (signal FPE). Set up trapping for floating point exceptions (signal FPE).
Controlled by two env vars: Defined by controlDict InfoSwitch entries:
- \par FOAM_SIGFPE - \par trapFpe
Exception trapping Enable floating point exception trapping.
- \par FOAM_SETNAN
Initialization of all malloced memory to NaN. If FOAM_SIGFPE
also set, this will cause usage of uninitialized scalars to trigger
an abort.
Can be used either directly through the static member functions or - \par setNaN
through the scope of the object (constructor sets trapping; destructor Initialization all malloced memory to NaN.
restores original). 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 SourceFiles
sigFpe.C sigFpe.C
@ -73,12 +80,20 @@ class sigFpe
{ {
// Private data // 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_;
//- Flag to indicate floating point trapping is currently active
static bool sigActive_;
//- Saved old signal trapping setting //- Saved old signal trapping setting
static struct sigaction oldAction_; static struct sigaction oldAction_;
//- Flag to indicate floating point trapping is enabled
static bool sigFpeActive_;
// Static data members // Static data members
@ -90,6 +105,11 @@ class sigFpe
public: public:
// Public data
//- Flag to indicate mallocNan is enabled
static bool mallocNanActive_;
// Constructors // Constructors
@ -103,6 +123,11 @@ public:
// Member functions // 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();
//- Activate SIGFPE signal handler when FOAM_SIGFPE is %set //- Activate SIGFPE signal handler when FOAM_SIGFPE is %set
// Fill memory with NaN when FOAM_SETNAN is %set // Fill memory with NaN when FOAM_SETNAN is %set
static void set(const bool verbose); static void set(const bool verbose);
@ -110,16 +135,13 @@ public:
//- Deactivate SIGFPE signal handler and NaN memory initialisation //- Deactivate SIGFPE signal handler and NaN memory initialisation
static void unset(const bool verbose); static void unset(const bool verbose);
//- Flag to indicate mallocNan is enabled
static bool mallocNanActive_;
#ifdef LINUX #ifdef LINUX
//- Malloc function which initializes to NaN //- Malloc function which initializes to NaN
static void* mallocNan(size_t size); static void* mallocNan(size_t size);
#endif #endif
//- Fill block of data with NaN //- Fill block of data with NaN
static void fillNan(UList<scalar>&); static void fillNan(UList<scalar>& lst);
}; };

View File

@ -86,7 +86,7 @@ void Foam::sigQuit::set(const bool verbose)
if (sigaction(SIGQUIT, &newAction, &oldAction_) < 0) if (sigaction(SIGQUIT, &newAction, &oldAction_) < 0)
{ {
FatalErrorInFunction FatalErrorInFunction
<< "Cannot call sigQuit::set() more than once" << "Cannot call more than once"
<< abort(FatalError); << abort(FatalError);
} }
sigActive_ = true; sigActive_ = true;
@ -101,7 +101,7 @@ void Foam::sigQuit::unset(const bool)
if (sigaction(SIGQUIT, &oldAction_, nullptr) < 0) if (sigaction(SIGQUIT, &oldAction_, nullptr) < 0)
{ {
FatalErrorInFunction FatalErrorInFunction
<< "Cannot set SIGQUIT trapping" << "Cannot unset SIGQUIT trapping"
<< abort(FatalError); << abort(FatalError);
} }
sigActive_ = false; sigActive_ = false;

View File

@ -86,7 +86,7 @@ void Foam::sigSegv::set(const bool)
if (sigaction(SIGSEGV, &newAction, &oldAction_) < 0) if (sigaction(SIGSEGV, &newAction, &oldAction_) < 0)
{ {
FatalErrorInFunction FatalErrorInFunction
<< "Cannot call sigSegv::set() more than once" << "Cannot call more than once"
<< abort(FatalError); << abort(FatalError);
} }
sigActive_ = true; sigActive_ = true;
@ -101,7 +101,7 @@ void Foam::sigSegv::unset(const bool)
if (sigaction(SIGSEGV, &oldAction_, nullptr) < 0) if (sigaction(SIGSEGV, &oldAction_, nullptr) < 0)
{ {
FatalErrorInFunction FatalErrorInFunction
<< "Cannot set SIGSEGV trapping" << "Cannot unset SIGSEGV trapping"
<< abort(FatalError); << abort(FatalError);
} }
sigActive_ = false; sigActive_ = false;

View File

@ -78,7 +78,6 @@ addstopAtWriteNowSignalToOpt addstopAtWriteNowSignalToOpt_
Foam::Time const* Foam::sigStopAtWriteNow::runTimePtr_ = nullptr; Foam::Time const* Foam::sigStopAtWriteNow::runTimePtr_ = nullptr;
struct sigaction Foam::sigStopAtWriteNow::oldAction_; struct sigaction Foam::sigStopAtWriteNow::oldAction_;
@ -109,7 +108,8 @@ void Foam::sigStopAtWriteNow::sigHandler(int)
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::sigStopAtWriteNow::sigStopAtWriteNow(){} Foam::sigStopAtWriteNow::sigStopAtWriteNow()
{}
Foam::sigStopAtWriteNow::sigStopAtWriteNow Foam::sigStopAtWriteNow::sigStopAtWriteNow

View File

@ -67,6 +67,7 @@ class sigStopAtWriteNow
// Private Member Functions // Private Member Functions
//- Handler for caught signals
static void sigHandler(int); static void sigHandler(int);

View File

@ -33,13 +33,13 @@ License
namespace Foam namespace Foam
{ {
// Signal number to catch // Signal number to catch
int sigWriteNow::signal_ int sigWriteNow::signal_
( (
debug::optimisationSwitch("writeNowSignal", -1) debug::optimisationSwitch("writeNowSignal", -1)
); );
// Register re-reader // Register re-reader
class addwriteNowSignalToOpt class addwriteNowSignalToOpt
: :
@ -75,7 +75,6 @@ addwriteNowSignalToOpt addwriteNowSignalToOpt_("writeNowSignal");
Foam::Time* Foam::sigWriteNow::runTimePtr_ = nullptr; Foam::Time* Foam::sigWriteNow::runTimePtr_ = nullptr;
struct sigaction Foam::sigWriteNow::oldAction_; struct sigaction Foam::sigWriteNow::oldAction_;

View File

@ -66,6 +66,7 @@ class sigWriteNow
// Private Member Functions // Private Member Functions
//- Handler for caught signals
static void sigHandler(int); static void sigHandler(int);

View File

@ -8,8 +8,8 @@ cd ${0%/*} || exit 1 # Run from this directory
runParallel $(getApplication) runParallel $(getApplication)
unset FOAM_SIGFPE # Disable trapping of floating-point exceptions
runParallel -s reconstruct redistributePar -reconstruct FOAM_SIGFPE=false runParallel -s reconstruct redistributePar -reconstruct
# A bit more testing of decomposing # A bit more testing of decomposing
\cp system/controlDict_nextWrite system/controlDict \cp system/controlDict_nextWrite system/controlDict