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 char* title)
127 :
128  std::exception(),
129  messageStream(title, messageStream::FATAL),
130  functionName_("unknown"),
131  sourceFileName_("unknown"),
132  sourceFileLineNumber_(0),
133  throwing_(false),
134  messageStreamPtr_(nullptr)
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_(nullptr)
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_(nullptr)
159 {
160  if (err.messageStreamPtr_ && (err.messageStreamPtr_->count() > 0))
161  {
163  }
164 }
165 
166 
167 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
168 
170 {}
171 
172 
173 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
174 
175 Foam::OSstream& Foam::error::operator()
176 (
177  const string& functionName
178 )
179 {
180  functionName_ = functionName;
181  sourceFileName_.clear();
182  sourceFileLineNumber_ = -1;
183 
184  return this->stream();
185 }
186 
187 
188 Foam::OSstream& Foam::error::operator()
189 (
190  const char* functionName,
191  const char* sourceFileName,
192  const int sourceFileLineNumber
193 )
194 {
195  functionName_.clear();
196  sourceFileName_.clear();
197 
198  if (functionName)
199  {
200  // With nullptr protection
201  functionName_.assign(functionName);
202  }
203  if (sourceFileName)
204  {
205  // With nullptr protection
206  sourceFileName_.assign(sourceFileName);
207  }
208  sourceFileLineNumber_ = sourceFileLineNumber;
209 
210  return this->stream();
211 }
212 
213 
214 Foam::OSstream& Foam::error::operator()
215 (
216  const string& functionName,
217  const char* sourceFileName,
218  const int sourceFileLineNumber
219 )
220 {
221  return operator()
222  (
223  functionName.c_str(),
224  sourceFileName,
225  sourceFileLineNumber
226  );
227 }
228 
229 
230 Foam::error::operator Foam::dictionary() const
231 {
232  dictionary errDict;
233 
234  string oneLineMessage(message());
235  oneLineMessage.replaceAll("\n", " ");
236 
237  errDict.add("type", word("Foam::error"));
238  errDict.add("message", oneLineMessage);
239  errDict.add("function", functionName());
240  errDict.add("sourceFile", sourceFileName());
241  errDict.add("sourceFileLineNumber", sourceFileLineNumber());
242 
243  return errDict;
244 }
245 
246 
247 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
248 
249 void Foam::error::exiting(const int errNo, const bool isAbort)
250 {
251  if (throwing_)
252  {
253  if (!isAbort)
254  {
255  // Make a copy of the error to throw
256  error errorException(*this);
257 
258  // Reset the message buffer for the next error message
259  error::clear();
260 
261  throw errorException;
262  return;
263  }
264  }
265  else if (JobInfo::constructed)
266  {
267  jobInfo.add("FatalError", operator dictionary());
268  JobInfo::shutdown(isAbort || error::useAbort());
269  }
271  simpleExit(errNo, isAbort);
272 }
273 
274 
275 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
276 
277 void Foam::error::simpleExit(const int errNo, const bool isAbort)
278 {
279  if (error::useAbort())
280  {
281  Perr<< nl << *this << nl
282  << "\nFOAM aborting (FOAM_ABORT set)\n" << endl;
284  std::abort();
285  }
286  else if (UPstream::parRun())
287  {
288  if (isAbort)
289  {
290  Perr<< nl << *this << nl
291  << "\nFOAM parallel run aborting\n" << endl;
293  UPstream::abort();
294  }
295  else
296  {
297  Perr<< nl << *this << nl
298  << "\nFOAM parallel run exiting\n" << endl;
299  UPstream::exit(errNo);
300  }
301  }
302  else
303  {
304  if (isAbort)
305  {
306  Perr<< nl << *this << nl
307  << "\nFOAM aborting\n" << endl;
309 
310  #ifdef _WIN32
311  std::exit(1); // Prefer exit() to avoid unnecessary warnings
312  #else
313  std::abort();
314  #endif
315  }
316  else
317  {
318  Perr<< nl << *this << nl
319  << "\nFOAM exiting\n" << endl;
320  std::exit(errNo);
321  }
322  }
323 }
324 
325 
326 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
327 
329 {
330  if (!messageStreamPtr_)
331  {
332  messageStreamPtr_ = std::make_unique<OStringStream>();
333  }
334  else if (!messageStreamPtr_->good())
335  {
336  Perr<< nl
337  << "error::stream() : error stream has failed"
338  << endl;
339  abort();
340  }
341 
342  return *messageStreamPtr_;
343 }
344 
345 
347 {
348  if (messageStreamPtr_)
349  {
350  return messageStreamPtr_->str();
351  }
352 
353  return string();
354 }
355 
356 
357 void Foam::error::clear() const
358 {
359  if (messageStreamPtr_)
360  {
361  messageStreamPtr_->reset();
362  }
363 }
364 
366 void Foam::error::exit(const int errNo)
367 {
368  exiting(errNo, false);
369 }
370 
372 void Foam::error::abort()
373 {
374  exiting(1, true);
375 }
376 
377 
378 void Foam::error::write(Ostream& os, const bool withTitle) const
379 {
380  if (os.bad())
381  {
382  return;
383  }
384 
385  os << nl;
386  if (withTitle && !title().empty())
387  {
388  os << title().c_str()
389  << "(openfoam-" << foamVersion::api;
390 
391  if (foamVersion::patched())
392  {
393  // Patch-level, when defined
394  os << " patch=" << foamVersion::patch.c_str();
395  }
396  os << ')' << nl;
397  }
398  os << message().c_str();
399 
400 
401  const label lineNo = sourceFileLineNumber();
402 
403  if (messageStream::level >= 2 && lineNo && !functionName().empty())
404  {
405  os << nl << nl
406  << " From " << functionName().c_str() << nl;
407 
408  if (!sourceFileName().empty())
409  {
410  os << " in file " << sourceFileName().c_str();
411 
412  if (lineNo > 0)
413  {
414  os << " at line " << lineNo << '.';
415  }
416  }
417  }
418 }
419 
420 
421 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
422 
423 Foam::Ostream& Foam::operator<<(Ostream& os, const error& err)
424 {
425  err.write(os);
426  return os;
427 }
428 
429 
430 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
431 // Global error definitions
432 
433 Foam::error Foam::FatalError("--> FOAM FATAL ERROR: ");
434 
435 
436 // ************************************************************************* //
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 accumulated error messages.
Definition: error.C:350
bool bad() const noexcept
True if stream is corrupted.
Definition: IOstream.H:305
std::unique_ptr< OStringStream > messageStreamPtr_
Definition: error.H:91
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:1061
virtual ~error() noexcept
Destructor.
Definition: error.C:162
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:359
static bool warnAboutAge(const int version) noexcept
Test if an age warning should be emitted.
Definition: error.C:67
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:339
void abort()
Abort : used to stop code for fatal errors.
Definition: error.C:365
virtual void write(Ostream &os, const bool withTitle=true) const
Print error message.
Definition: error.C:371
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:321
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1094
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:208
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
error(const char *title)
Construct from title string.
Definition: error.C:119
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:270