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