Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
00061 __malloc_hook = old_malloc_hook;
00062
00063
00064 result = malloc (size);
00065
00066
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
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
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
00119 jobInfo.signalEnd();
00120
00121 error::printStack(Perr);
00122
00123
00124 raise(SIGFPE);
00125 }
00126
00127 #endif
00128
00129
00130
00131
00132 Foam::sigFpeImpl::sigFpeImpl()
00133 {
00134 oldAction_.sa_handler = NULL;
00135 }
00136
00137
00138
00139
00140 Foam::sigFpeImpl::~sigFpeImpl()
00141 {
00142 #ifdef FOAM_USE_FPE_HANDLING
00143 if (env("FOAM_SIGFPE"))
00144 {
00145
00146
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
00164 if (oldAction_.sa_handler)
00165 {
00166 __malloc_hook = old_malloc_hook;
00167 }
00168
00169 }
00170 #endif
00171 }
00172
00173
00174
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
00254 __malloc_hook = Foam::sigFpeImpl::my_malloc_hook;
00255
00256 }
00257 #endif
00258 }
00259
00260
00261