FreeFOAM The Cross-Platform CFD Toolkit
sigFpeImpl.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd.
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include <OpenFOAM/error.H>
27 #include "sigFpeImpl.H"
28 
29 #include <OpenFOAM/JobInfo.H>
30 #include <OpenFOAM/OSspecific.H>
31 #include <OpenFOAM/IOstreams.H>
32 
33 #if defined(FOAM_HAVE_FEENABLEEXCEPT) && defined(FOAM_HAVE_FENV_H)
34 # ifndef __USE_GNU
35 # define __USE_GNU
36 # endif
37 # include <fenv.h>
38 #elif defined(FOAM_HAVE_HANDLE_SIGFPES) && defined(FOAM_HAVE_SIGFPE_H)
39 # include <sigfpe.h>
40 #endif
41 
42 #ifdef FOAM_USE_MALLOC_HOOK
43 # include <malloc.h>
44 #endif
45 
46 
47 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
48 
49 struct sigaction Foam::sigFpeImpl::oldAction_;
50 
51 
52 #ifdef FOAM_USE_MALLOC_HOOK
53 
54 void *(*Foam::sigFpeImpl::old_malloc_hook)(size_t, const void *) = NULL;
55 
56 void* Foam::sigFpeImpl::my_malloc_hook(size_t size, const void *caller)
57 {
58  void *result;
59 
60  // Restore all old hooks
61  __malloc_hook = old_malloc_hook;
62 
63  // Call recursively
64  result = malloc (size);
65 
66  // initialize to signalling nan
67 # ifdef SP
68 
69  const uint32_t sNAN = 0x7ff7fffflu;
70 
71  int nScalars = size / sizeof(scalar);
72 
73  uint32_t* dPtr = reinterpret_cast<uint32_t*>(result);
74 
75  for (int i = 0; i < nScalars; i++)
76  {
77  *dPtr++ = sNAN;
78  }
79 
80 # else
81 
82  const uint64_t sNAN = 0x7ff7ffffffffffffllu;
83 
84  int nScalars = size/sizeof(scalar);
85 
86  uint64_t* dPtr = reinterpret_cast<uint64_t*>(result);
87 
88  for (int i = 0; i < nScalars; i++)
89  {
90  *dPtr++ = sNAN;
91  }
92 
93 # endif
94 
95  // Restore our own hooks
96  __malloc_hook = my_malloc_hook;
97 
98  return result;
99 }
100 
101 #endif
102 
103 
104 #ifdef FOAM_USE_FPE_HANDLING
105 
106 void Foam::sigFpeImpl::sigFpeHandler(int)
107 {
108  // Reset old handling
109  if (sigaction(SIGFPE, &oldAction_, NULL) < 0)
110  {
112  (
113  "Foam::sigFpeImpl::sigFpeHandler()"
114  ) << "Cannot reset SIGFPE trapping"
115  << abort(FatalError);
116  }
117 
118  // Update jobInfo file
119  jobInfo.signalEnd();
120 
122 
123  // Throw signal (to old handler)
124  raise(SIGFPE);
125 }
126 
127 #endif
128 
129 
130 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
131 
133 {
134  oldAction_.sa_handler = NULL;
135 }
136 
137 
138 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
139 
141 {
142 #ifdef FOAM_USE_FPE_HANDLING
143  if (env("FOAM_SIGFPE"))
144  {
145 
146  // Reset signal
147  if (oldAction_.sa_handler && sigaction(SIGFPE, &oldAction_, NULL) < 0)
148  {
150  (
151  "Foam::sigFpeImpl::~sigFpeImpl()"
152  ) << "Cannot reset SIGFPE trapping"
153  << abort(FatalError);
154  }
155 
156  }
157 #endif
158 
159 #ifdef FOAM_USE_MALLOC_HOOK
160  if (env("FOAM_SETNAN"))
161  {
162 
163  // Reset to standard malloc
164  if (oldAction_.sa_handler)
165  {
166  __malloc_hook = old_malloc_hook;
167  }
168 
169  }
170 #endif
171 }
172 
173 
174 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
175 
176 void Foam::sigFpeImpl::set(const bool verbose)
177 {
178  if (oldAction_.sa_handler)
179  {
181  (
182  "Foam::sigFpeImpl::set()"
183  ) << "Cannot call sigFpeImpl::set() more than once"
184  << abort(FatalError);
185  }
186 
187 #ifdef FOAM_USE_FPE_HANDLING
188  if (env("FOAM_SIGFPE"))
189  {
190 # if defined(FOAM_HAVE_FEENABLEEXCEPT)
191  if (verbose)
192  {
193  Info<< "SigFpe : Enabling floating point exception trapping"
194  << " (FOAM_SIGFPE)." << endl;
195  }
196 
197  feenableexcept
198  (
199  FE_DIVBYZERO
200  | FE_INVALID
201  | FE_OVERFLOW
202  );
203 
204  struct sigaction newAction;
205  newAction.sa_handler = sigFpeHandler;
206  newAction.sa_flags = SA_NODEFER;
207  sigemptyset(&newAction.sa_mask);
208  if (sigaction(SIGFPE, &newAction, &oldAction_) < 0)
209  {
211  (
212  "Foam::sigFpeImpl::set()"
213  ) << "Cannot set SIGFPE trapping"
214  << abort(FatalError);
215  }
216 
217 
218 # elif defined(FOAM_HAVE_HANDLE_SIGFPES)
219 
220  sigfpe_[_DIVZERO].abort=1;
221  sigfpe_[_OVERFL].abort=1;
222  sigfpe_[_INVALID].abort=1;
223 
224  sigfpe_[_DIVZERO].trace=1;
225  sigfpe_[_OVERFL].trace=1;
226  sigfpe_[_INVALID].trace=1;
227 
228  handle_sigfpes
229  (
230  _ON,
231  _EN_DIVZERO
232  | _EN_INVALID
233  | _EN_OVERFL,
234  0,
235  _ABORT_ON_ERROR,
236  NULL
237  );
238 
239 # endif
240  }
241 #endif // FOAM_USE_FPE_HANDLING
242 
243 
244 #ifdef FOAM_USE_MALLOC_HOOK
245  if (env("FOAM_SETNAN"))
246  {
247  if (verbose)
248  {
249  Info<< "SetNaN : Initialising allocated memory to NaN"
250  << " (FOAM_SETNAN)." << endl;
251  }
252 
253  // Set our malloc
254  __malloc_hook = Foam::sigFpeImpl::my_malloc_hook;
255 
256  }
257 #endif
258 }
259 
260 
261 // ************************ vim: set sw=4 sts=4 et: ************************ //