error.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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2014 OpenFOAM Foundation
9  Copyright (C) 2015-2021 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "error.H"
30 #include "fileName.H"
31 #include "dictionary.H"
32 #include "JobInfo.H"
33 #include "Pstream.H"
34 #include "StringStream.H"
35 #include "foamVersion.H"
36 #include "OSspecific.H"
37 #include "Switch.H"
38 
39 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
40 
41 bool Foam::error::master(const label communicator)
42 {
43  // Trap negative value for comm as 'default'. This avoids direct use
44  // of Pstream::worldComm which may not have been initialised
45 
46  return
47  (
49  ? (communicator < 0 ? UPstream::master() : UPstream::master(communicator))
50  : true
51  );
52 }
53 
54 
55 bool Foam::error::warnAboutAge(const int version) noexcept
56 {
57  // No warning for 0 (unversioned) or -ve values (silent versioning)
58  return ((version > 0) && (version < foamVersion::api));
59 }
60 
61 
62 bool Foam::error::warnAboutAge(const char* what, const int version)
63 {
64  // No warning for 0 (unversioned) or -ve values (silent versioning).
65  // Also no warning for (version >= foamVersion::api), which
66  // can be used to denote future expiry dates of transition features.
67 
68  const bool old = ((version > 0) && (version < foamVersion::api));
69 
70  if (old)
71  {
72  const int months =
73  (
74  // YYMM -> months
75  (12 * (foamVersion::api/100) + (foamVersion::api % 100))
76  - (12 * (version/100) + (version % 100))
77  );
78 
79  if (version < 1000)
80  {
81  // For things that predate YYMM versioning (eg, 240 for version 2.4)
82  std::cerr
83  << " This " << what << " is very old.\n"
84  << std::endl;
85  }
86  else
87  {
88  std::cerr
89  << " This " << what << " is " << months << " months old.\n"
90  << std::endl;
91  }
92  }
93 
94  return old;
95 }
96 
97 
99 {
100  // FOAM_ABORT env set and contains bool-type value
101  return static_cast<bool>(Switch::find(Foam::getEnv("FOAM_ABORT")));
102 }
103 
104 
105 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
106 
107 Foam::error::error(const string& title)
108 :
109  std::exception(),
110  messageStream(title, messageStream::FATAL),
111  functionName_("unknown"),
112  sourceFileName_("unknown"),
113  sourceFileLineNumber_(0),
114  throwing_(false),
115  messageStreamPtr_(new OStringStream())
116 {}
117 
118 
120 :
121  std::exception(),
122  messageStream(errDict),
123  functionName_(errDict.get<string>("functionName")),
124  sourceFileName_(errDict.get<string>("sourceFileName")),
125  sourceFileLineNumber_(errDict.get<label>("sourceFileLineNumber")),
126  throwing_(false),
127  messageStreamPtr_(new OStringStream())
128 {}
129 
130 
132 :
133  std::exception(),
134  messageStream(err),
135  functionName_(err.functionName_),
136  sourceFileName_(err.sourceFileName_),
137  sourceFileLineNumber_(err.sourceFileLineNumber_),
138  throwing_(err.throwing_),
139  messageStreamPtr_(new OStringStream(*err.messageStreamPtr_))
140 {}
141 
142 
143 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
144 
146 {}
147 
148 
149 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
150 
151 Foam::OSstream& Foam::error::operator()
152 (
153  const string& functionName
154 )
155 {
156  functionName_ = functionName;
157  sourceFileName_.clear();
158  sourceFileLineNumber_ = -1;
159 
160  return operator OSstream&();
161 }
162 
163 
164 Foam::OSstream& Foam::error::operator()
165 (
166  const char* functionName,
167  const char* sourceFileName,
168  const int sourceFileLineNumber
169 )
170 {
171  functionName_.clear();
172  sourceFileName_.clear();
173 
174  if (functionName)
175  {
176  // With nullptr protection
177  functionName_.assign(functionName);
178  }
179  if (sourceFileName)
180  {
181  // With nullptr protection
182  sourceFileName_.assign(sourceFileName);
183  }
184  sourceFileLineNumber_ = sourceFileLineNumber;
185 
186  return this->stream();
187 }
188 
189 
190 Foam::OSstream& Foam::error::operator()
191 (
192  const string& functionName,
193  const char* sourceFileName,
194  const int sourceFileLineNumber
195 )
196 {
197  return operator()
198  (
199  functionName.c_str(),
200  sourceFileName,
201  sourceFileLineNumber
202  );
203 }
204 
205 
206 Foam::error::operator Foam::dictionary() const
207 {
208  dictionary errDict;
209 
210  string oneLineMessage(message());
211  oneLineMessage.replaceAll("\n", " ");
212 
213  errDict.add("type", word("Foam::error"));
214  errDict.add("message", oneLineMessage);
215  errDict.add("function", functionName());
216  errDict.add("sourceFile", sourceFileName());
217  errDict.add("sourceFileLineNumber", sourceFileLineNumber());
218 
219  return errDict;
220 }
221 
222 
223 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
224 
225 void Foam::error::exiting(const int errNo, const bool isAbort)
226 {
227  if (throwing_)
228  {
229  if (!isAbort)
230  {
231  // Make a copy of the error to throw
232  error errorException(*this);
233 
234  // Reset the message buffer for the next error message
235  messageStreamPtr_->reset();
236 
237  throw errorException;
238  return;
239  }
240  }
241  else if (JobInfo::constructed)
242  {
243  jobInfo.add("FatalError", operator dictionary());
244  JobInfo::shutdown(isAbort || error::useAbort());
245  }
246 
247  simpleExit(errNo, isAbort);
248 }
249 
250 
251 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
252 
253 void Foam::error::simpleExit(const int errNo, const bool isAbort)
254 {
255  if (error::useAbort())
256  {
257  Perr<< nl << *this << nl
258  << "\nFOAM aborting (FOAM_ABORT set)\n" << endl;
260  std::abort();
261  }
262  else if (UPstream::parRun())
263  {
264  if (isAbort)
265  {
266  Perr<< nl << *this << nl
267  << "\nFOAM parallel run aborting\n" << endl;
269  UPstream::abort();
270  }
271  else
272  {
273  Perr<< nl << *this << nl
274  << "\nFOAM parallel run exiting\n" << endl;
275  UPstream::exit(errNo);
276  }
277  }
278  else
279  {
280  if (isAbort)
281  {
282  Perr<< nl << *this << nl
283  << "\nFOAM aborting\n" << endl;
285 
286  #ifdef _WIN32
287  std::exit(1); // Prefer exit() to avoid unnecessary warnings
288  #else
289  std::abort();
290  #endif
291  }
292  else
293  {
294  Perr<< nl << *this << nl
295  << "\nFOAM exiting\n" << endl;
296  std::exit(errNo);
297  }
298  }
299 }
300 
301 
302 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
303 
305 {
306  // Don't need (messageStreamPtr_) check - always allocated
307  if (!messageStreamPtr_->good())
308  {
309  Perr<< nl
310  << "error::stream() : error stream has failed"
311  << endl;
312  abort();
313  }
314 
315  return *messageStreamPtr_;
316 }
317 
318 
320 {
321  return messageStreamPtr_->str();
322 }
323 
324 
325 void Foam::error::clear() const
326 {
327  return messageStreamPtr_->reset();
328 }
329 
330 
331 void Foam::error::exit(const int errNo)
332 {
333  exiting(errNo, false);
334 }
335 
336 
338 {
339  exiting(1, true);
340 }
341 
342 
343 void Foam::error::write(Ostream& os, const bool withTitle) const
344 {
345  if (os.bad())
346  {
347  return;
348  }
349 
350  os << nl;
351  if (withTitle && !title().empty())
352  {
353  os << title().c_str()
354  << "(openfoam-" << foamVersion::api;
355 
356  if (foamVersion::patched())
357  {
358  // Patch-level, when defined
359  os << " patch=" << foamVersion::patch.c_str();
360  }
361  os << ')' << nl;
362  }
363  os << message().c_str();
364 
365 
366  const label lineNo = sourceFileLineNumber();
367 
368  if (error::level >= 2 && lineNo && !functionName().empty())
369  {
370  os << nl << nl
371  << " From " << functionName().c_str() << nl;
372 
373  if (!sourceFileName().empty())
374  {
375  os << " in file " << sourceFileName().c_str();
376 
377  if (lineNo > 0)
378  {
379  os << " at line " << lineNo << '.';
380  }
381  }
382  }
383 }
384 
385 
386 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
387 
389 {
390  err.write(os);
391  return os;
392 }
393 
394 
395 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
396 // Global error definitions
397 
398 Foam::error Foam::FatalError("--> FOAM FATAL ERROR: ");
399 
400 
401 // ************************************************************************* //
OSspecific.H
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
Foam::error::printStack
static void printStack(Ostream &os)
Helper function to print a stack.
Definition: dummyPrintStack.C:36
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::foamVersion::patched
bool patched()
Foam::messageStream
Handle output messages in a simple, consistent stream-based manner.
Definition: messageStream.H:73
Foam::messageStream::level
static int level
The output level (verbosity) of messages.
Definition: messageStream.H:112
Foam::UPstream::master
static bool master(const label communicator=worldComm)
Am I the master process.
Definition: UPstream.H:457
StringStream.H
Input/output from string buffers.
Foam::UPstream::abort
static void abort()
Call MPI_Abort with no other checks or cleanup.
Definition: UPstream.C:70
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::string
A class for handling character strings derived from std::string.
Definition: string.H:76
Foam::Switch::find
static Switch find(const std::string &str)
Definition: Switch.C:151
Foam::getEnv
string getEnv(const std::string &envName)
Get environment value for given envName.
Definition: MSwindows.C:371
Foam::operator<<
Ostream & operator<<(Ostream &, const boundaryPatch &p)
Write boundaryPatch as dictionary entries (without surrounding braces)
Definition: boundaryPatch.C:83
Foam::foamVersion::api
const int api
Foam::error::error
error(const string &title)
Construct from title string.
Definition: error.C:107
error.H
fileName.H
Switch.H
Foam::OSstream
Generic output stream using a standard (STL) stream.
Definition: OSstream.H:54
Foam::JobInfo::shutdown
static void shutdown()
Simple shutdown (finalize) of JobInfo.
Definition: JobInfo.C:98
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
os
OBJstream os(runTime.globalPath()/outputName)
Pstream.H
Foam::IOstream::bad
bool bad() const noexcept
True if stream is corrupted.
Definition: IOstream.H:251
Foam::error::message
string message() const
The accumulated error message.
Definition: error.C:319
Foam::error::useAbort
static bool useAbort()
True if FOAM_ABORT is on.
Definition: error.C:98
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Foam::error::exit
void exit(const int errNo=1)
Exit : can be called for any error to exit program.
Definition: error.C:331
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::foamVersion::version
const std::string version
OpenFOAM version (name or stringified number) as a std::string.
Foam::jobInfo
JobInfo jobInfo
Definition: JobInfo.C:49
Foam::error::~error
virtual ~error() noexcept
Destructor.
Definition: error.C:145
Foam::Perr
prefixOSstream Perr
OSstream wrapped stderr (std::cerr) with parallel prefix.
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::error::stream
OSstream & stream()
Return OSstream for output operations.
Definition: error.C:304
Foam::foamVersion::patch
const std::string patch
OpenFOAM patch number as a std::string.
Foam::JobInfo::constructed
static bool constructed
Global value for constructed job info.
Definition: JobInfo.H:101
Foam::UPstream::parRun
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:433
Foam::error::abort
void abort()
Abort : used to stop code for fatal errors.
Definition: error.C:337
Foam::OStringStream
Output to string buffer, using a OSstream. Always UNCOMPRESSED.
Definition: StringStream.H:227
Foam::error::master
static bool master(const label communicator=-1)
Definition: error.C:41
Foam::error::simpleExit
void simpleExit(const int errNo, const bool isAbort)
Exit or abort, without throwing or job control handling.
Definition: error.C:253
dictionary.H
Foam::error::clear
void clear() const
Clear any messages.
Definition: error.C:325
JobInfo.H
Foam::PtrListOps::get
List< ReturnType > get(const UPtrList< T > &list, const AccessOp &aop)
Foam::error::warnAboutAge
static bool warnAboutAge(const int version) noexcept
Test if an age warning should be emitted.
Definition: error.C:55
Foam::dictionary::add
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:640
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::error::write
virtual void write(Ostream &os, const bool withTitle=true) const
Print error message.
Definition: error.C:343
Foam::error
Class to handle errors and exceptions in a simple, consistent stream-based manner.
Definition: error.H:73
Foam::UPstream::exit
static void exit(int errNo=1)
Shutdown (finalize) MPI as required and exit program with errNo.
Definition: UPstream.C:63
foamVersion.H