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 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 "Switch.H"
41 
42 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
43 
44 bool Foam::error::master(const label communicator)
45 {
46  // Trap negative value for comm as 'default'. This avoids direct use
47  // of UPstream::worldComm which may have not yet been initialised
48 
49  return
50  (
52  ? (communicator < 0 ? UPstream::master() : UPstream::master(communicator))
53  : true
54  );
55 }
56 
57 
59 {
60  // No warning for 0 (unversioned) or -ve values (silent versioning)
61  return ((version > 0) && (version < foamVersion::api));
62 }
63 
64 
65 bool Foam::error::warnAboutAge(const char* what, const int version)
66 {
67  // No warning for 0 (unversioned) or -ve values (silent versioning).
68  // Also no warning for (version >= foamVersion::api), which
69  // can be used to denote future expiry dates of transition features.
70 
71  const bool old = ((version > 0) && (version < foamVersion::api));
72 
73  if (old)
74  {
75  const int months =
76  (
77  // YYMM -> months
78  (12 * (foamVersion::api/100) + (foamVersion::api % 100))
79  - (12 * (version/100) + (version % 100))
80  );
81 
82  if (version < 1000)
83  {
84  // For things that predate YYMM versioning (eg, 240 for version 2.4)
85  std::cerr
86  << " This " << what << " is very old.\n"
87  << std::endl;
88  }
89  else
90  {
91  std::cerr
92  << " This " << what << " is " << months << " months old.\n"
93  << std::endl;
94  }
95  }
96 
97  return old;
98 }
99 
100 
102 {
103  // FOAM_ABORT env set and contains bool-type value
104  return static_cast<bool>(Switch::find(Foam::getEnv("FOAM_ABORT")));
105 }
106 
107 
108 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
109 
110 Foam::error::error(const string& title)
111 :
112  std::exception(),
113  messageStream(title, messageStream::FATAL),
114  functionName_("unknown"),
115  sourceFileName_("unknown"),
116  sourceFileLineNumber_(0),
117  throwing_(false),
118  messageStreamPtr_(new OStringStream())
119 {}
120 
121 
122 Foam::error::error(const dictionary& errDict)
123 :
124  std::exception(),
125  messageStream(errDict),
126  functionName_(errDict.get<string>("functionName")),
127  sourceFileName_(errDict.get<string>("sourceFileName")),
128  sourceFileLineNumber_(errDict.get<label>("sourceFileLineNumber")),
129  throwing_(false),
130  messageStreamPtr_(new OStringStream())
131 {}
132 
133 
134 Foam::error::error(const error& err)
135 :
136  std::exception(),
137  messageStream(err),
138  functionName_(err.functionName_),
139  sourceFileName_(err.sourceFileName_),
140  sourceFileLineNumber_(err.sourceFileLineNumber_),
141  throwing_(err.throwing_),
142  messageStreamPtr_(new OStringStream(*err.messageStreamPtr_))
143 {}
144 
145 
146 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
147 
149 {}
150 
151 
152 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
153 
154 Foam::OSstream& Foam::error::operator()
155 (
156  const string& functionName
157 )
158 {
159  functionName_ = functionName;
160  sourceFileName_.clear();
161  sourceFileLineNumber_ = -1;
162 
163  return operator OSstream&();
164 }
165 
166 
167 Foam::OSstream& Foam::error::operator()
168 (
169  const char* functionName,
170  const char* sourceFileName,
171  const int sourceFileLineNumber
172 )
173 {
174  functionName_.clear();
175  sourceFileName_.clear();
176 
177  if (functionName)
178  {
179  // With nullptr protection
180  functionName_.assign(functionName);
181  }
182  if (sourceFileName)
183  {
184  // With nullptr protection
185  sourceFileName_.assign(sourceFileName);
186  }
187  sourceFileLineNumber_ = sourceFileLineNumber;
188 
189  return this->stream();
190 }
191 
192 
193 Foam::OSstream& Foam::error::operator()
194 (
195  const string& functionName,
196  const char* sourceFileName,
197  const int sourceFileLineNumber
198 )
199 {
200  return operator()
201  (
202  functionName.c_str(),
203  sourceFileName,
204  sourceFileLineNumber
205  );
206 }
207 
208 
209 Foam::error::operator Foam::dictionary() const
210 {
211  dictionary errDict;
212 
213  string oneLineMessage(message());
214  oneLineMessage.replaceAll("\n", " ");
215 
216  errDict.add("type", word("Foam::error"));
217  errDict.add("message", oneLineMessage);
218  errDict.add("function", functionName());
219  errDict.add("sourceFile", sourceFileName());
220  errDict.add("sourceFileLineNumber", sourceFileLineNumber());
221 
222  return errDict;
223 }
224 
225 
226 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
227 
228 void Foam::error::exiting(const int errNo, const bool isAbort)
229 {
230  if (throwing_)
231  {
232  if (!isAbort)
233  {
234  // Make a copy of the error to throw
235  error errorException(*this);
236 
237  // Reset the message buffer for the next error message
238  messageStreamPtr_->reset();
239 
240  throw errorException;
241  return;
242  }
243  }
244  else if (JobInfo::constructed)
245  {
246  jobInfo.add("FatalError", operator dictionary());
247  JobInfo::shutdown(isAbort || error::useAbort());
248  }
250  simpleExit(errNo, isAbort);
251 }
252 
253 
254 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
255 
256 void Foam::error::simpleExit(const int errNo, const bool isAbort)
257 {
258  if (error::useAbort())
259  {
260  Perr<< nl << *this << nl
261  << "\nFOAM aborting (FOAM_ABORT set)\n" << endl;
263  std::abort();
264  }
265  else if (UPstream::parRun())
266  {
267  if (isAbort)
268  {
269  Perr<< nl << *this << nl
270  << "\nFOAM parallel run aborting\n" << endl;
272  UPstream::abort();
273  }
274  else
275  {
276  Perr<< nl << *this << nl
277  << "\nFOAM parallel run exiting\n" << endl;
278  UPstream::exit(errNo);
279  }
280  }
281  else
282  {
283  if (isAbort)
284  {
285  Perr<< nl << *this << nl
286  << "\nFOAM aborting\n" << endl;
288 
289  #ifdef _WIN32
290  std::exit(1); // Prefer exit() to avoid unnecessary warnings
291  #else
292  std::abort();
293  #endif
294  }
295  else
296  {
297  Perr<< nl << *this << nl
298  << "\nFOAM exiting\n" << endl;
299  std::exit(errNo);
300  }
301  }
302 }
303 
304 
305 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
306 
308 {
309  // Don't need (messageStreamPtr_) check - always allocated
310  if (!messageStreamPtr_->good())
311  {
312  Perr<< nl
313  << "error::stream() : error stream has failed"
314  << endl;
315  abort();
316  }
317 
318  return *messageStreamPtr_;
319 }
320 
323 {
324  return messageStreamPtr_->str();
325 }
326 
328 void Foam::error::clear() const
329 {
330  return messageStreamPtr_->reset();
331 }
332 
334 void Foam::error::exit(const int errNo)
335 {
336  exiting(errNo, false);
337 }
338 
340 void Foam::error::abort()
341 {
342  exiting(1, true);
343 }
344 
345 
346 void Foam::error::write(Ostream& os, const bool withTitle) const
347 {
348  if (os.bad())
349  {
350  return;
351  }
352 
353  os << nl;
354  if (withTitle && !title().empty())
355  {
356  os << title().c_str()
357  << "(openfoam-" << foamVersion::api;
358 
359  if (foamVersion::patched())
360  {
361  // Patch-level, when defined
362  os << " patch=" << foamVersion::patch.c_str();
363  }
364  os << ')' << nl;
365  }
366  os << message().c_str();
367 
368 
369  const label lineNo = sourceFileLineNumber();
370 
371  if (error::level >= 2 && lineNo && !functionName().empty())
372  {
373  os << nl << nl
374  << " From " << functionName().c_str() << nl;
375 
376  if (!sourceFileName().empty())
377  {
378  os << " in file " << sourceFileName().c_str();
379 
380  if (lineNo > 0)
381  {
382  os << " at line " << lineNo << '.';
383  }
384  }
385  }
386 }
387 
388 
389 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
390 
391 Foam::Ostream& Foam::operator<<(Ostream& os, const error& err)
392 {
393  err.write(os);
394  return os;
395 }
396 
397 
398 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
399 // Global error definitions
400 
401 Foam::error Foam::FatalError("--> FOAM FATAL ERROR: ");
402 
403 
404 // ************************************************************************* //
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:321
bool bad() const noexcept
True if stream is corrupted.
Definition: IOstream.H:305
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:120
Input/output from string buffers.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
static void shutdown()
Simple shutdown (finalize) of JobInfo.
Definition: JobInfo.C:94
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1004
virtual ~error() noexcept
Destructor.
Definition: error.C:141
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:637
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:327
static bool warnAboutAge(const int version) noexcept
Test if an age warning should be emitted.
Definition: error.C:51
error(const string &title)
Construct from title string.
Definition: error.C:103
Class to handle errors and exceptions in a simple, consistent stream-based manner.
Definition: error.H:69
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:94
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:37
string message() const
The accumulated error message.
Definition: error.C:315
void abort()
Abort : used to stop code for fatal errors.
Definition: error.C:333
virtual void write(Ostream &os, const bool withTitle=true) const
Print error message.
Definition: error.C:339
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:55
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:76
const std::string version
OpenFOAM version (name or stringified number) as a std::string.
OSstream & stream()
Return OSstream for output operations.
Definition: error.C:300
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1037
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
void simpleExit(const int errNo, const bool isAbort)
Exit or abort, without throwing or job control handling.
Definition: error.C:249