FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

sigFpeImpl.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*---------------------------------------------------------------------------*/
00025 
00026 #include <OpenFOAM/error.H>
00027 #include "sigFpeImpl.H"
00028 
00029 #include <OpenFOAM/JobInfo.H>
00030 #include <OpenFOAM/OSspecific.H>
00031 #include <OpenFOAM/IOstreams.H>
00032 
00033 #if defined(FOAM_HAVE_FEENABLEEXCEPT) && defined(FOAM_HAVE_FENV_H)
00034 #   ifndef __USE_GNU
00035 #       define __USE_GNU
00036 #   endif
00037 #   include <fenv.h>
00038 #elif defined(FOAM_HAVE_HANDLE_SIGFPES) && defined(FOAM_HAVE_SIGFPE_H)
00039 #   include <sigfpe.h>
00040 #endif
00041 
00042 #ifdef FOAM_USE_MALLOC_HOOK
00043 #   include <malloc.h>
00044 #endif
00045 
00046 
00047 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00048 
00049 struct sigaction Foam::sigFpeImpl::oldAction_;
00050 
00051 
00052 #ifdef FOAM_USE_MALLOC_HOOK
00053 
00054 void *(*Foam::sigFpeImpl::old_malloc_hook)(size_t, const void *) = NULL;
00055 
00056 void* Foam::sigFpeImpl::my_malloc_hook(size_t size, const void *caller)
00057 {
00058     void *result;
00059 
00060     // Restore all old hooks
00061     __malloc_hook = old_malloc_hook;
00062 
00063     // Call recursively
00064     result = malloc (size);
00065 
00066     // initialize to signalling nan
00067 #   ifdef SP
00068 
00069     const uint32_t sNAN = 0x7ff7fffflu;
00070 
00071     int nScalars = size / sizeof(scalar);
00072 
00073     uint32_t* dPtr = reinterpret_cast<uint32_t*>(result);
00074 
00075     for (int i = 0; i < nScalars; i++)
00076     {
00077         *dPtr++ = sNAN;
00078     }
00079 
00080 #   else
00081 
00082     const uint64_t sNAN = 0x7ff7ffffffffffffllu;
00083 
00084     int nScalars = size/sizeof(scalar);
00085 
00086     uint64_t* dPtr = reinterpret_cast<uint64_t*>(result);
00087 
00088     for (int i = 0; i < nScalars; i++)
00089     {
00090         *dPtr++ = sNAN;
00091     }
00092 
00093 #   endif
00094 
00095     // Restore our own hooks
00096     __malloc_hook = my_malloc_hook;
00097 
00098     return result;
00099 }
00100 
00101 #endif
00102 
00103 
00104 #ifdef FOAM_USE_FPE_HANDLING
00105 
00106 void Foam::sigFpeImpl::sigFpeHandler(int)
00107 {
00108     // Reset old handling
00109     if (sigaction(SIGFPE, &oldAction_, NULL) < 0)
00110     {
00111         FatalErrorIn
00112         (
00113             "Foam::sigFpeImpl::sigFpeHandler()"
00114         )   << "Cannot reset SIGFPE trapping"
00115             << abort(FatalError);
00116     }
00117 
00118     // Update jobInfo file
00119     jobInfo.signalEnd();
00120 
00121     error::printStack(Perr);
00122 
00123     // Throw signal (to old handler)
00124     raise(SIGFPE);
00125 }
00126 
00127 #endif
00128 
00129 
00130 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00131 
00132 Foam::sigFpeImpl::sigFpeImpl()
00133 {
00134     oldAction_.sa_handler = NULL;
00135 }
00136 
00137 
00138 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
00139 
00140 Foam::sigFpeImpl::~sigFpeImpl()
00141 {
00142 #ifdef FOAM_USE_FPE_HANDLING
00143     if (env("FOAM_SIGFPE"))
00144     {
00145 
00146         // Reset signal
00147         if (oldAction_.sa_handler && sigaction(SIGFPE, &oldAction_, NULL) < 0)
00148         {
00149             FatalErrorIn
00150             (
00151                 "Foam::sigFpeImpl::~sigFpeImpl()"
00152             )   << "Cannot reset SIGFPE trapping"
00153                 << abort(FatalError);
00154         }
00155 
00156     }
00157 #endif
00158 
00159 #ifdef FOAM_USE_MALLOC_HOOK
00160     if (env("FOAM_SETNAN"))
00161     {
00162 
00163         // Reset to standard malloc
00164         if (oldAction_.sa_handler)
00165         {
00166             __malloc_hook = old_malloc_hook;
00167         }
00168 
00169     }
00170 #endif
00171 }
00172 
00173 
00174 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00175 
00176 void Foam::sigFpeImpl::set(const bool verbose)
00177 {
00178     if (oldAction_.sa_handler)
00179     {
00180         FatalErrorIn
00181         (
00182             "Foam::sigFpeImpl::set()"
00183         )   << "Cannot call sigFpeImpl::set() more than once"
00184             << abort(FatalError);
00185     }
00186 
00187 #ifdef FOAM_USE_FPE_HANDLING
00188     if (env("FOAM_SIGFPE"))
00189     {
00190 #   if defined(FOAM_HAVE_FEENABLEEXCEPT)
00191         if (verbose)
00192         {
00193             Info<< "SigFpe : Enabling floating point exception trapping"
00194                 << " (FOAM_SIGFPE)." << endl;
00195         }
00196 
00197         feenableexcept
00198         (
00199             FE_DIVBYZERO
00200           | FE_INVALID
00201           | FE_OVERFLOW
00202         );
00203 
00204         struct sigaction newAction;
00205         newAction.sa_handler = sigFpeHandler;
00206         newAction.sa_flags = SA_NODEFER;
00207         sigemptyset(&newAction.sa_mask);
00208         if (sigaction(SIGFPE, &newAction, &oldAction_) < 0)
00209         {
00210             FatalErrorIn
00211             (
00212                 "Foam::sigFpeImpl::set()"
00213             )   << "Cannot set SIGFPE trapping"
00214                 << abort(FatalError);
00215         }
00216 
00217 
00218 #   elif defined(FOAM_HAVE_HANDLE_SIGFPES)
00219 
00220         sigfpe_[_DIVZERO].abort=1;
00221         sigfpe_[_OVERFL].abort=1;
00222         sigfpe_[_INVALID].abort=1;
00223 
00224         sigfpe_[_DIVZERO].trace=1;
00225         sigfpe_[_OVERFL].trace=1;
00226         sigfpe_[_INVALID].trace=1;
00227 
00228         handle_sigfpes
00229         (
00230             _ON,
00231             _EN_DIVZERO
00232           | _EN_INVALID
00233           | _EN_OVERFL,
00234             0,
00235             _ABORT_ON_ERROR,
00236             NULL
00237         );
00238 
00239 #   endif
00240     }
00241 #endif // FOAM_USE_FPE_HANDLING
00242 
00243 
00244 #ifdef FOAM_USE_MALLOC_HOOK
00245     if (env("FOAM_SETNAN"))
00246     {
00247         if (verbose)
00248         {
00249             Info<< "SetNaN : Initialising allocated memory to NaN"
00250                 << " (FOAM_SETNAN)." << endl;
00251         }
00252 
00253         // Set our malloc
00254         __malloc_hook = Foam::sigFpeImpl::my_malloc_hook;
00255 
00256     }
00257 #endif
00258 }
00259 
00260 
00261 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines