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-2023 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 Note
28  Included by global/globals.C
29 
30 \*---------------------------------------------------------------------------*/
31 
32 #include "error.H"
33 #include "fileName.H"
34 #include "dictionary.H"
35 #include "JobInfo.H"
36 #include "UPstream.H"
37 #include "StringStream.H"
38 #include "foamVersion.H"
39 #include "OSspecific.H"
40 #include "Enum.H"
41 #include "Switch.H"
42 
43 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
44 
45 const Foam::Enum
46 <
48 >
50 ({
51  { handlerTypes::DEFAULT, "default" },
52  { handlerTypes::IGNORE, "ignore" },
53  { handlerTypes::WARN, "warn" },
54  { handlerTypes::STRICT, "strict" },
55 });
56 
57 
58 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
59 
60 bool Foam::error::master(const label communicator)
61 {
62  // Trap negative value for comm as 'default'. This avoids direct use
63  // of UPstream::worldComm which may have not yet been initialised
64 
65  return
66  (
68  ? (communicator < 0 ? UPstream::master() : UPstream::master(communicator))
69  : true
70  );
71 }
72 
73 
75 {
76  // No warning for 0 (unversioned) or -ve values (silent versioning)
77  return ((version > 0) && (version < foamVersion::api));
78 }
79 
80 
81 bool Foam::error::warnAboutAge(const char* what, const int version)
82 {
83  // No warning for 0 (unversioned) or -ve values (silent versioning).
84  // Also no warning for (version >= foamVersion::api), which
85  // can be used to denote future expiry dates of transition features.
86 
87  const bool old = ((version > 0) && (version < foamVersion::api));
88 
89  if (old)
90  {
91  const int months =
92  (
93  // YYMM -> months
94  (12 * (foamVersion::api/100) + (foamVersion::api % 100))
95  - (12 * (version/100) + (version % 100))
96  );
97 
98  if (version < 1000)
99  {
100  // For things that predate YYMM versioning (eg, 240 for version 2.4)
101  std::cerr
102  << " This " << what << " is very old.\n"
103  << std::endl;
104  }
105  else
106  {
107  std::cerr
108  << " This " << what << " is " << months << " months old.\n"
109  << std::endl;
110  }
111  }
112 
113  return old;
114 }
115 
116 
118 {
119  // FOAM_ABORT env set and contains bool-type value
120  return static_cast<bool>(Switch::find(Foam::getEnv("FOAM_ABORT")));
121 }
122 
123 
124 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
125 
126 Foam::error::error(const string& title)
127 :
128  std::exception(),
129  messageStream(title, messageStream::FATAL),
130  functionName_("unknown"),
131  sourceFileName_("unknown"),
132  sourceFileLineNumber_(0),
133  throwing_(false),
134  messageStreamPtr_(new OStringStream())
135 {}
136 
137 
138 Foam::error::error(const dictionary& errDict)
139 :
140  std::exception(),
141  messageStream(errDict),
142  functionName_(errDict.get<string>("functionName")),
143  sourceFileName_(errDict.get<string>("sourceFileName")),
144  sourceFileLineNumber_(errDict.get<label>("sourceFileLineNumber")),
145  throwing_(false),
146  messageStreamPtr_(new OStringStream())
147 {}
148 
149 
150 Foam::error::error(const error& err)
151 :
152  std::exception(),
153  messageStream(err),
154  functionName_(err.functionName_),
155  sourceFileName_(err.sourceFileName_),
156  sourceFileLineNumber_(err.sourceFileLineNumber_),
157  throwing_(err.throwing_),
158  messageStreamPtr_(new OStringStream(*err.messageStreamPtr_))
159 {}
160 
161 
162 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
163 
165 {}
166 
167 
168 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
169 
170 Foam::OSstream& Foam::error::operator()
171 (
172  const string& functionName
173 )
174 {
175  functionName_ = functionName;
176  sourceFileName_.clear();
177  sourceFileLineNumber_ = -1;
178 
179  return operator OSstream&();
180 }
181 
182 
183 Foam::OSstream& Foam::error::operator()
184 (
185  const char* functionName,
186  const char* sourceFileName,
187  const int sourceFileLineNumber
188 )
189 {
190  functionName_.clear();
191  sourceFileName_.clear();
192 
193  if (functionName)
194  {
195  // With nullptr protection
196  functionName_.assign(functionName);
197  }
198  if (sourceFileName)
199  {
200  // With nullptr protection
201  sourceFileName_.assign(sourceFileName);
202  }
203  sourceFileLineNumber_ = sourceFileLineNumber;
204 
205  return this->stream();
206 }
207 
208 
209 Foam::OSstream& Foam::error::operator()
210 (
211  const string& functionName,
212  const char* sourceFileName,
213  const int sourceFileLineNumber
214 )
215 {
216  return operator()
217  (
218  functionName.c_str(),
219  sourceFileName,
220  sourceFileLineNumber
221  );
222 }
223 
224 
225 Foam::error::operator Foam::dictionary() const
226 {
227  dictionary errDict;
228 
229  string oneLineMessage(message());
230  oneLineMessage.replaceAll("\n", " ");
231 
232  errDict.add("type", word("Foam::error"));
233  errDict.add("message", oneLineMessage);
234  errDict.add("function", functionName());
235  errDict.add("sourceFile", sourceFileName());
236  errDict.add("sourceFileLineNumber", sourceFileLineNumber());
237 
238  return errDict;
239 }
240 
241 
242 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
243 
244 void Foam::error::exiting(const int errNo, const bool isAbort)
245 {
246  if (throwing_)
247  {
248  if (!isAbort)
249  {
250  // Make a copy of the error to throw
251  error errorException(*this);
252 
253  // Reset the message buffer for the next error message
254  messageStreamPtr_->reset();
255 
256  throw errorException;
257  return;
258  }
259  }
260  else if (JobInfo::constructed)
261  {
262  jobInfo.add("FatalError", operator dictionary());
263  JobInfo::shutdown(isAbort || error::useAbort());
264  }
266  simpleExit(errNo, isAbort);
267 }
268 
269 
270 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
271 
272 void Foam::error::simpleExit(const int errNo, const bool isAbort)
273 {
274  if (error::useAbort())
275  {
276  Perr<< nl << *this << nl
277  << "\nFOAM aborting (FOAM_ABORT set)\n" << endl;
279  std::abort();
280  }
281  else if (UPstream::parRun())
282  {
283  if (isAbort)
284  {
285  Perr<< nl << *this << nl
286  << "\nFOAM parallel run aborting\n" << endl;
288  UPstream::abort();
289  }
290  else
291  {
292  Perr<< nl << *this << nl
293  << "\nFOAM parallel run exiting\n" << endl;
294  UPstream::exit(errNo);
295  }
296  }
297  else
298  {
299  if (isAbort)
300  {
301  Perr<< nl << *this << nl
302  << "\nFOAM aborting\n" << endl;
304 
305  #ifdef _WIN32
306  std::exit(1); // Prefer exit() to avoid unnecessary warnings
307  #else
308  std::abort();
309  #endif
310  }
311  else
312  {
313  Perr<< nl << *this << nl
314  << "\nFOAM exiting\n" << endl;
315  std::exit(errNo);
316  }
317  }
318 }
319 
320 
321 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
322 
324 {
325  // Don't need (messageStreamPtr_) check - always allocated
326  if (!messageStreamPtr_->good())
327  {
328  Perr<< nl
329  << "error::stream() : error stream has failed"
330  << endl;
331  abort();
332  }
333 
334  return *messageStreamPtr_;
335 }
336 
339 {
340  return messageStreamPtr_->str();
341 }
342 
344 void Foam::error::clear() const
345 {
346  return messageStreamPtr_->reset();
347 }
348 
350 void Foam::error::exit(const int errNo)
351 {
352  exiting(errNo, false);
353 }
354 
356 void Foam::error::abort()
357 {
358  exiting(1, true);
359 }
360 
361 
362 void Foam::error::write(Ostream& os, const bool withTitle) const
363 {
364  if (os.bad())
365  {
366  return;
367  }
368 
369  os << nl;
370  if (withTitle && !title().empty())
371  {
372  os << title().c_str()
373  << "(openfoam-" << foamVersion::api;
374 
375  if (foamVersion::patched())
376  {
377  // Patch-level, when defined
378  os << " patch=" << foamVersion::patch.c_str();
379  }
380  os << ')' << nl;
381  }
382  os << message().c_str();
383 
384 
385  const label lineNo = sourceFileLineNumber();
386 
387  if (error::level >= 2 && lineNo && !functionName().empty())
388  {
389  os << nl << nl
390  << " From " << functionName().c_str() << nl;
391 
392  if (!sourceFileName().empty())
393  {
394  os << " in file " << sourceFileName().c_str();
395 
396  if (lineNo > 0)
397  {
398  os << " at line " << lineNo << '.';
399  }
400  }
401  }
402 }
403 
404 
405 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
406 
407 Foam::Ostream& Foam::operator<<(Ostream& os, const error& err)
408 {
409  err.write(os);
410  return os;
411 }
412 
413 
414 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
415 // Global error definitions
416 
417 Foam::error Foam::FatalError("--> FOAM FATAL ERROR: ");
418 
419 
420 // ************************************************************************* //
List< ReturnType > get(const UPtrList< T > &list, const AccessOp &aop)
List of values generated by applying the access operation to each list item.
prefixOSstream Perr
OSstream wrapped stderr (std::cerr) with parallel prefix.
Generic output stream using a standard (STL) stream.
Definition: OSstream.H:50
void clear() const
Clear any messages.
Definition: error.C:337
bool bad() const noexcept
True if stream is corrupted.
Definition: IOstream.H:305
handlerTypes
Handling of errors. The exact handling depends on the local context.
Definition: error.H:109
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
Input/output from string buffers.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
static void shutdown()
Simple shutdown (finalize) of JobInfo.
Definition: JobInfo.C:94
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1049
virtual ~error() noexcept
Destructor.
Definition: error.C:157
bool patched()
Test if the patch string appears to be in use, which is when it is defined (non-zero).
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:625
Handle output messages in a simple, consistent stream-based manner.
Definition: messageStream.H:70
string getEnv(const std::string &envName)
Get environment value for given envName.
Definition: POSIX.C:339
void exit(const int errNo=1)
Exit : can be called for any error to exit program.
Definition: error.C:343
static bool warnAboutAge(const int version) noexcept
Test if an age warning should be emitted.
Definition: error.C:67
error(const string &title)
Construct from title string.
Definition: error.C:119
Class to handle errors and exceptions in a simple, consistent stream-based manner.
Definition: error.H:70
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
static void exit(int errNo=1)
Shutdown (finalize) MPI as required and exit program with errNo.
Definition: UPstream.C:55
static bool useAbort()
True if FOAM_ABORT is on.
Definition: error.C:110
static bool master(const label communicator=-1)
Like Pstream::master but with a Pstream::parRun guard in case Pstream has not yet been initialised...
Definition: error.C:53
string message() const
The accumulated error message.
Definition: error.C:331
void abort()
Abort : used to stop code for fatal errors.
Definition: error.C:349
virtual void write(Ostream &os, const bool withTitle=true) const
Print error message.
Definition: error.C:355
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
errorManip< error > abort(error &err)
Definition: errorManip.H:139
const int api
OpenFOAM api number (integer) corresponding to the value of OPENFOAM at the time of compilation...
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
const direction noexcept
Definition: Scalar.H:258
OBJstream os(runTime.globalPath()/outputName)
static void abort()
Call MPI_Abort with no other checks or cleanup.
Definition: UPstream.C:62
Ostream & operator<<(Ostream &, const boundaryPatch &p)
Write boundaryPatch as dictionary entries (without surrounding braces)
Definition: boundaryPatch.C:77
const std::string version
OpenFOAM version (name or stringified number) as a std::string.
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition: error.H:64
OSstream & stream()
Return OSstream for output operations.
Definition: error.C:316
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1082
const std::string patch
OpenFOAM patch number as a std::string.
JobInfo jobInfo
Definition: JobInfo.C:45
static void printStack(Ostream &os, int size=-1)
Helper function to print a stack, with optional upper limit.
A class for handling character strings derived from std::string.
Definition: string.H:72
Output to string buffer, using a OSstream. Always UNCOMPRESSED.
Definition: StringStream.H:256
static Switch find(const std::string &str)
Find switchType for the given string, returning as a Switch that can be tested for good() or bad()...
Definition: Switch.C:147
static int level
The output level (verbosity) of messages.
static bool constructed
Global value for constructed job info.
Definition: JobInfo.H:115
static const Enum< handlerTypes > handlerNames
Names of the error handler types.
Definition: error.H:120
void simpleExit(const int errNo, const bool isAbort)
Exit or abort, without throwing or job control handling.
Definition: error.C:265