From c50368ecc67f442b3b6c843ea914f9aedd1f7f8a Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Wed, 5 Jul 2017 17:49:37 +0200 Subject: [PATCH] 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. --- .../redistributePar/redistributePar.C | 4 +- bin/tools/foamConfigurePaths | 40 +++++------- etc/bashrc | 12 ++-- etc/controlDict | 8 +++ etc/cshrc | 12 ++-- src/OSspecific/POSIX/signals/sigFpe.C | 65 ++++++++++++++----- src/OSspecific/POSIX/signals/sigFpe.H | 56 +++++++++++----- src/OSspecific/POSIX/signals/sigQuit.C | 8 +-- src/OSspecific/POSIX/signals/sigSegv.C | 4 +- .../POSIX/signals/sigStopAtWriteNow.C | 4 +- .../POSIX/signals/sigStopAtWriteNow.H | 1 + src/OSspecific/POSIX/signals/sigWriteNow.C | 3 +- src/OSspecific/POSIX/signals/sigWriteNow.H | 1 + .../interDyMFoam/RAS/motorBike/Allrun | 4 +- 14 files changed, 139 insertions(+), 83 deletions(-) diff --git a/applications/utilities/parallelProcessing/redistributePar/redistributePar.C b/applications/utilities/parallelProcessing/redistributePar/redistributePar.C index 5c4862f2b8..b61718dbff 100644 --- a/applications/utilities/parallelProcessing/redistributePar/redistributePar.C +++ b/applications/utilities/parallelProcessing/redistributePar/redistributePar.C @@ -59,6 +59,7 @@ Usage \*---------------------------------------------------------------------------*/ #include "argList.H" +#include "sigFpe.H" #include "Time.H" #include "fvMesh.H" #include "fvMeshTools.H" @@ -2277,7 +2278,7 @@ int main(int argc, char *argv[]) bool newTimes = args.optionFound("newTimes"); - if (env("FOAM_SIGFPE")) + if (Foam::sigFpe::requested()) { WarningInFunction << "Detected floating point exception trapping (FOAM_SIGFPE)." @@ -2287,7 +2288,6 @@ int main(int argc, char *argv[]) } - const HashSet selectedFields(0); const HashSet selectedLagrangianFields(0); diff --git a/bin/tools/foamConfigurePaths b/bin/tools/foamConfigurePaths index dca869faad..a17b6a033e 100755 --- a/bin/tools/foamConfigurePaths +++ b/bin/tools/foamConfigurePaths @@ -39,8 +39,9 @@ usage: ${0##*/} -foamVersion ver specify project version (eg, 1612) -projectName name specify project directory name (eg, openfoam1612) -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' - -SP | -DP specify 'WM_PRECISION_OPTION' -system name specify 'system' compiler to be used -third name specify 'ThirdParty' compiler to be used -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) -vtk ver specify 'vtk_version' (eg, VTK-7.1.0) -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) mpfr-VERSION for ThirdParty gcc (mpfr-system for system library) mpc-VERSION for ThirdParty gcc (mpc-system for system library) @@ -251,6 +252,18 @@ do 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) # Replace WM_LABEL_SIZE=... optionValue="${1#-int}" @@ -258,13 +271,6 @@ do adjusted=true ;; - -SP | -DP) - # Replace WM_PRECISION_OPTION=... - optionValue="${1#-}" - replace etc/bashrc WM_PRECISION_OPTION "$optionValue" - adjusted=true - ;; - -system) # Replace WM_COMPILER_TYPE=... and WM_COMPILER=... [ "$#" -ge 2 ] || die "'$1' option requires an argument" @@ -471,20 +477,8 @@ do adjusted=true ;; - -sigfpe) - # Enable FOAM_SIGFPE handling - _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" + -sigfpe | -no-sigfpe) + echo "Enable/disable FOAM_SIGFPE now via controlDict" 1>&2 ;; *) diff --git a/etc/bashrc b/etc/bashrc index 2060a58690..97c8152b33 100644 --- a/etc/bashrc +++ b/etc/bashrc @@ -96,13 +96,13 @@ export WM_MPLIB=SYSTEMOPENMPI # WM_OSTYPE = POSIX #export WM_OSTYPE=POSIX -#- Floating-point signal handling: -# set or unset -export FOAM_SIGFPE= +#- Alternative to 'trapFpe' controlDict entry +# for floating-point exceptions (true|false) +#export FOAM_SIGFPE=true -#- memory initialisation: -# set or unset -#export FOAM_SETNAN= +#- Alternative to 'setNaN' controlDict entry +# for memory initialisation (true|false) +#export FOAM_SETNAN=false ################################################################################ diff --git a/etc/controlDict b/etc/controlDict index c73b387510..2b435d1fe4 100644 --- a/etc/controlDict +++ b/etc/controlDict @@ -79,6 +79,14 @@ OptimisationSwitches // global reduction, even if multi-pass is not needed) 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) writeNowSignal -1; // 10; diff --git a/etc/cshrc b/etc/cshrc index 3208ca0ac8..6c42ebdf61 100644 --- a/etc/cshrc +++ b/etc/cshrc @@ -93,13 +93,13 @@ setenv WM_MPLIB SYSTEMOPENMPI # WM_OSTYPE = POSIX #setenv WM_OSTYPE POSIX -#- Floating-point signal handling: -# set or unset -setenv FOAM_SIGFPE +#- Alternative to 'trapFpe' controlDict entry +# for floating-point exceptions (true|false) +#setenv FOAM_SIGFPE true -#- memory initialisation: -# set or unset -#setenv FOAM_SETNAN +#- Alternative to 'setNaN' controlDict entry +# for memory initialisation (true|false) +#setenv FOAM_SETNAN false ################################################################################ diff --git a/src/OSspecific/POSIX/signals/sigFpe.C b/src/OSspecific/POSIX/signals/sigFpe.C index 609de778ab..513a6d6d36 100644 --- a/src/OSspecific/POSIX/signals/sigFpe.C +++ b/src/OSspecific/POSIX/signals/sigFpe.C @@ -28,6 +28,7 @@ License #include "JobInfo.H" #include "OSspecific.H" #include "IOstreams.H" +#include "Switch.H" #ifdef LINUX_GNUC #ifndef __USE_GNU @@ -43,17 +44,41 @@ License // * * * * * * * * * * * * * * 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_; -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& lst) { lst = std::numeric_limits::signaling_NaN(); } -bool Foam::sigFpe::mallocNanActive_ = false; - #ifdef LINUX extern "C" @@ -128,9 +153,15 @@ Foam::sigFpe::~sigFpe() // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // +bool Foam::sigFpe::requested() +{ + return isTrue("FOAM_SIGFPE", switchFpe_); +} + + void Foam::sigFpe::set(const bool verbose) { - if (!sigFpeActive_ && env("FOAM_SIGFPE")) + if (!sigActive_ && requested()) { bool supported = false; @@ -155,7 +186,7 @@ void Foam::sigFpe::set(const bool verbose) << abort(FatalError); } - sigFpeActive_ = true; + sigActive_ = true; #elif defined(sgiN32) || defined(sgiN32Gcc) supported = true; @@ -179,28 +210,28 @@ void Foam::sigFpe::set(const bool verbose) nullptr ); - sigFpeActive_ = true; + sigActive_ = true; #endif if (verbose) { + Info<< "trapFpe: Floating point exception trapping "; + if (supported) { - Info<< "sigFpe : Enabling floating point exception trapping" - << " (FOAM_SIGFPE)." << endl; + Info<< "enabled (FOAM_SIGFPE)." << endl; } else { - Info<< "sigFpe : Floating point exception trapping" - << " - not supported on this platform" << endl; + Info<< "- not supported on this platform" << endl; } } } - if (env("FOAM_SETNAN")) + if (isTrue("FOAM_SETNAN", switchNan_)) { #ifdef LINUX mallocNanActive_ = true; @@ -208,15 +239,15 @@ void Foam::sigFpe::set(const bool verbose) if (verbose) { + Info<< "setNaN : Initialise allocated memory to NaN "; + if (mallocNanActive_) { - Info<< "SetNaN : Initialising allocated memory to NaN" - << " (FOAM_SETNAN)." << endl; + Info<< "enabled (FOAM_SETNAN)." << endl; } else { - Info<< "SetNaN : Initialise allocated memory to NaN" - << " - not supported on this platform" << endl; + Info<< " - not supported on this platform" << endl; } } } @@ -227,7 +258,7 @@ void Foam::sigFpe::unset(const bool verbose) { #ifdef LINUX_GNUC // Reset signal - if (sigFpeActive_) + if (sigActive_) { if (verbose) { @@ -256,7 +287,7 @@ void Foam::sigFpe::unset(const bool verbose) << "Cannot reset SIGFPE trapping" << abort(FatalError); } - sigFpeActive_ = false; + sigActive_ = false; } #endif diff --git a/src/OSspecific/POSIX/signals/sigFpe.H b/src/OSspecific/POSIX/signals/sigFpe.H index a4473825bb..fe1c49b638 100644 --- a/src/OSspecific/POSIX/signals/sigFpe.H +++ b/src/OSspecific/POSIX/signals/sigFpe.H @@ -27,17 +27,24 @@ Class Description Set up trapping for floating point exceptions (signal FPE). - Controlled by two env vars: - - \par FOAM_SIGFPE - 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. + Defined by controlDict InfoSwitch entries: + - \par trapFpe + Enable floating point exception trapping. - Can be used either directly through the static member functions or - through the scope of the object (constructor sets trapping; destructor - restores original). + - \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.C @@ -73,12 +80,20 @@ 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_; + + //- Flag to indicate floating point trapping is currently active + static bool sigActive_; + //- Saved old signal trapping setting static struct sigaction oldAction_; - //- Flag to indicate floating point trapping is enabled - static bool sigFpeActive_; - // Static data members @@ -90,6 +105,11 @@ class sigFpe public: + // Public data + + //- Flag to indicate mallocNan is enabled + static bool mallocNanActive_; + // Constructors @@ -103,6 +123,11 @@ public: // 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 // Fill memory with NaN when FOAM_SETNAN is %set static void set(const bool verbose); @@ -110,16 +135,13 @@ public: //- Deactivate SIGFPE signal handler and NaN memory initialisation static void unset(const bool verbose); - //- Flag to indicate mallocNan is enabled - static bool mallocNanActive_; - #ifdef LINUX //- Malloc function which initializes to NaN static void* mallocNan(size_t size); #endif //- Fill block of data with NaN - static void fillNan(UList&); + static void fillNan(UList& lst); }; diff --git a/src/OSspecific/POSIX/signals/sigQuit.C b/src/OSspecific/POSIX/signals/sigQuit.C index 9b0a7443f0..b8352dd832 100644 --- a/src/OSspecific/POSIX/signals/sigQuit.C +++ b/src/OSspecific/POSIX/signals/sigQuit.C @@ -86,7 +86,7 @@ void Foam::sigQuit::set(const bool verbose) if (sigaction(SIGQUIT, &newAction, &oldAction_) < 0) { FatalErrorInFunction - << "Cannot call sigQuit::set() more than once" + << "Cannot call more than once" << abort(FatalError); } sigActive_ = true; @@ -100,9 +100,9 @@ void Foam::sigQuit::unset(const bool) { if (sigaction(SIGQUIT, &oldAction_, nullptr) < 0) { - FatalErrorInFunction - << "Cannot set SIGQUIT trapping" - << abort(FatalError); + FatalErrorInFunction + << "Cannot unset SIGQUIT trapping" + << abort(FatalError); } sigActive_ = false; } diff --git a/src/OSspecific/POSIX/signals/sigSegv.C b/src/OSspecific/POSIX/signals/sigSegv.C index 188c24495a..27cf667884 100644 --- a/src/OSspecific/POSIX/signals/sigSegv.C +++ b/src/OSspecific/POSIX/signals/sigSegv.C @@ -86,7 +86,7 @@ void Foam::sigSegv::set(const bool) if (sigaction(SIGSEGV, &newAction, &oldAction_) < 0) { FatalErrorInFunction - << "Cannot call sigSegv::set() more than once" + << "Cannot call more than once" << abort(FatalError); } sigActive_ = true; @@ -101,7 +101,7 @@ void Foam::sigSegv::unset(const bool) if (sigaction(SIGSEGV, &oldAction_, nullptr) < 0) { FatalErrorInFunction - << "Cannot set SIGSEGV trapping" + << "Cannot unset SIGSEGV trapping" << abort(FatalError); } sigActive_ = false; diff --git a/src/OSspecific/POSIX/signals/sigStopAtWriteNow.C b/src/OSspecific/POSIX/signals/sigStopAtWriteNow.C index 9808f91c11..1198daa6ad 100644 --- a/src/OSspecific/POSIX/signals/sigStopAtWriteNow.C +++ b/src/OSspecific/POSIX/signals/sigStopAtWriteNow.C @@ -78,7 +78,6 @@ addstopAtWriteNowSignalToOpt addstopAtWriteNowSignalToOpt_ Foam::Time const* Foam::sigStopAtWriteNow::runTimePtr_ = nullptr; - struct sigaction Foam::sigStopAtWriteNow::oldAction_; @@ -109,7 +108,8 @@ void Foam::sigStopAtWriteNow::sigHandler(int) // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // -Foam::sigStopAtWriteNow::sigStopAtWriteNow(){} +Foam::sigStopAtWriteNow::sigStopAtWriteNow() +{} Foam::sigStopAtWriteNow::sigStopAtWriteNow diff --git a/src/OSspecific/POSIX/signals/sigStopAtWriteNow.H b/src/OSspecific/POSIX/signals/sigStopAtWriteNow.H index bf83a350d7..22510310be 100644 --- a/src/OSspecific/POSIX/signals/sigStopAtWriteNow.H +++ b/src/OSspecific/POSIX/signals/sigStopAtWriteNow.H @@ -67,6 +67,7 @@ class sigStopAtWriteNow // Private Member Functions + //- Handler for caught signals static void sigHandler(int); diff --git a/src/OSspecific/POSIX/signals/sigWriteNow.C b/src/OSspecific/POSIX/signals/sigWriteNow.C index c226ff6e1f..01d13cfddf 100644 --- a/src/OSspecific/POSIX/signals/sigWriteNow.C +++ b/src/OSspecific/POSIX/signals/sigWriteNow.C @@ -33,13 +33,13 @@ License namespace Foam { - // Signal number to catch int sigWriteNow::signal_ ( debug::optimisationSwitch("writeNowSignal", -1) ); + // Register re-reader class addwriteNowSignalToOpt : @@ -75,7 +75,6 @@ addwriteNowSignalToOpt addwriteNowSignalToOpt_("writeNowSignal"); Foam::Time* Foam::sigWriteNow::runTimePtr_ = nullptr; - struct sigaction Foam::sigWriteNow::oldAction_; diff --git a/src/OSspecific/POSIX/signals/sigWriteNow.H b/src/OSspecific/POSIX/signals/sigWriteNow.H index 67506f7fa2..12fa7c3131 100644 --- a/src/OSspecific/POSIX/signals/sigWriteNow.H +++ b/src/OSspecific/POSIX/signals/sigWriteNow.H @@ -66,6 +66,7 @@ class sigWriteNow // Private Member Functions + //- Handler for caught signals static void sigHandler(int); diff --git a/tutorials/multiphase/interDyMFoam/RAS/motorBike/Allrun b/tutorials/multiphase/interDyMFoam/RAS/motorBike/Allrun index d22cdd2cc4..af3c3b444d 100755 --- a/tutorials/multiphase/interDyMFoam/RAS/motorBike/Allrun +++ b/tutorials/multiphase/interDyMFoam/RAS/motorBike/Allrun @@ -8,8 +8,8 @@ cd ${0%/*} || exit 1 # Run from this directory runParallel $(getApplication) -unset FOAM_SIGFPE -runParallel -s reconstruct redistributePar -reconstruct +# Disable trapping of floating-point exceptions +FOAM_SIGFPE=false runParallel -s reconstruct redistributePar -reconstruct # A bit more testing of decomposing \cp system/controlDict_nextWrite system/controlDict