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-2020 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 "StringStream.H"
31 #include "fileName.H"
32 #include "dictionary.H"
33 #include "JobInfo.H"
34 #include "Pstream.H"
35 #include "foamVersion.H"
36 #include "OSspecific.H"
37 #include "Switch.H"
38 
39 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
40 
41 void Foam::error::warnAboutAge(const char* what, const int version)
42 {
43  if (version <= 0)
44  {
45  // No warning for 0 (unversioned) or -ve values (silent versioning)
46  }
47  else if (version < 1000)
48  {
49  // Warning for things that predate the YYMM versioning
50  // (eg, 240 for version 2.4)
51  std::cerr
52  << " This " << what << " is considered to be VERY old!\n"
53  << std::endl;
54  }
55  else if (version < foamVersion::api)
56  {
57  const int months =
58  (
59  // YYMM -> months
60  (12 * (foamVersion::api/100) + (foamVersion::api % 100))
61  - (12 * (version/100) + (version % 100))
62  );
63 
64  std::cerr
65  << " This " << what << " is deemed to be " << months
66  << " months old.\n"
67  << std::endl;
68  }
69  // No warning for (foamVersion::api < version).
70  // We use this to denote future expiry dates of transition features.
71 }
72 
73 
75 {
76  // FOAM_ABORT env set and contains bool-type value
77  return static_cast<bool>(Switch::find(Foam::getEnv("FOAM_ABORT")));
78 }
79 
80 
81 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
82 
83 Foam::error::error(const string& title)
84 :
85  std::exception(),
86  messageStream(title, messageStream::FATAL),
87  functionName_("unknown"),
88  sourceFileName_("unknown"),
89  sourceFileLineNumber_(0),
90  throwing_(false),
91  messageStreamPtr_(new OStringStream())
92 {}
93 
94 
96 :
97  std::exception(),
98  messageStream(errDict),
99  functionName_(errDict.get<string>("functionName")),
100  sourceFileName_(errDict.get<string>("sourceFileName")),
101  sourceFileLineNumber_(errDict.get<label>("sourceFileLineNumber")),
102  throwing_(false),
103  messageStreamPtr_(new OStringStream())
104 {}
105 
106 
108 :
109  std::exception(),
110  messageStream(err),
111  functionName_(err.functionName_),
112  sourceFileName_(err.sourceFileName_),
113  sourceFileLineNumber_(err.sourceFileLineNumber_),
114  throwing_(err.throwing_),
115  messageStreamPtr_(new OStringStream(*err.messageStreamPtr_))
116 {}
117 
118 
119 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
120 
122 {}
123 
124 
125 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
126 
127 Foam::OSstream& Foam::error::operator()
128 (
129  const string& functionName
130 )
131 {
132  functionName_ = functionName;
133  sourceFileName_.clear();
134  sourceFileLineNumber_ = -1;
135 
136  return operator OSstream&();
137 }
138 
139 
140 Foam::OSstream& Foam::error::operator()
141 (
142  const char* functionName,
143  const char* sourceFileName,
144  const int sourceFileLineNumber
145 )
146 {
147  functionName_ = functionName;
148  sourceFileName_ = sourceFileName;
149  sourceFileLineNumber_ = sourceFileLineNumber;
150 
151  return operator OSstream&();
152 }
153 
154 
155 Foam::OSstream& Foam::error::operator()
156 (
157  const string& functionName,
158  const char* sourceFileName,
159  const int sourceFileLineNumber
160 )
161 {
162  return operator()
163  (
164  functionName.c_str(),
165  sourceFileName,
166  sourceFileLineNumber
167  );
168 }
169 
170 
171 Foam::error::operator Foam::OSstream&()
172 {
173  if (!messageStreamPtr_->good())
174  {
175  Perr<< nl
176  << "error::operator OSstream&() : error stream has failed"
177  << endl;
178  abort();
179  }
180 
181  return *messageStreamPtr_;
182 }
183 
184 
185 Foam::error::operator Foam::dictionary() const
186 {
187  dictionary errDict;
188 
189  string oneLineMessage(message());
190  oneLineMessage.replaceAll("\n", " ");
191 
192  errDict.add("type", word("Foam::error"));
193  errDict.add("message", oneLineMessage);
194  errDict.add("function", functionName());
195  errDict.add("sourceFile", sourceFileName());
196  errDict.add("sourceFileLineNumber", sourceFileLineNumber());
197 
198  return errDict;
199 }
200 
201 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
202 
203 void Foam::error::exitOrAbort(const int errNo, const bool isAbort)
204 {
205  if (!throwing_ && JobInfo::constructed)
206  {
207  jobInfo.add("FatalError", operator dictionary());
208  if (isAbort || error::useAbort())
209  {
210  jobInfo.abort();
211  }
212  else
213  {
214  jobInfo.exit();
215  }
216  }
217 
218  if (throwing_ && !isAbort)
219  {
220  // Make a copy of the error to throw
221  error errorException(*this);
222 
223  // Reset the message buffer for the next error message
224  messageStreamPtr_->reset();
225 
226  throw errorException;
227  }
228  else if (error::useAbort())
229  {
230  Perr<< nl << *this << nl
231  << "\nFOAM aborting (FOAM_ABORT set)\n" << endl;
233  std::abort();
234  }
235  else if (Pstream::parRun())
236  {
237  if (isAbort)
238  {
239  Perr<< nl << *this << nl
240  << "\nFOAM parallel run aborting\n" << endl;
242  Pstream::abort();
243  }
244  else
245  {
246  Perr<< nl << *this << nl
247  << "\nFOAM parallel run exiting\n" << endl;
248  Pstream::exit(errNo);
249  }
250  }
251  else
252  {
253  if (isAbort)
254  {
255  Perr<< nl << *this << nl
256  << "\nFOAM aborting\n" << endl;
258 
259  #ifdef _WIN32
260  std::exit(1); // Prefer exit() to avoid unnecessary warnings
261  #else
262  std::abort();
263  #endif
264  }
265  else
266  {
267  Perr<< nl << *this << nl
268  << "\nFOAM exiting\n" << endl;
269  std::exit(errNo);
270  }
271  }
272 }
273 
274 
275 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
276 
278 {
279  return messageStreamPtr_->str();
280 }
281 
282 
283 void Foam::error::clear() const
284 {
285  return messageStreamPtr_->reset();
286 }
287 
288 
289 void Foam::error::exit(const int errNo)
290 {
291  exitOrAbort(errNo, false);
292 }
293 
294 
296 {
297  exitOrAbort(1, true);
298 }
299 
300 
301 void Foam::error::write(Ostream& os, const bool includeTitle) const
302 {
303  if (os.bad())
304  {
305  return;
306  }
307 
308  os << nl;
309  if (includeTitle && !title().empty())
310  {
311  os << title().c_str()
312  << "(openfoam-" << foamVersion::api;
313 
314  if (foamVersion::patched())
315  {
316  // Patch-level, when defined
317  os << " patch=" << foamVersion::patch.c_str();
318  }
319  os << ')' << nl;
320  }
321  os << message().c_str();
322 
323 
324  const label lineNo = sourceFileLineNumber();
325 
326  if (error::level >= 2 && lineNo && !functionName().empty())
327  {
328  os << nl << nl
329  << " From " << functionName().c_str() << nl;
330 
331  if (!sourceFileName().empty())
332  {
333  os << " in file " << sourceFileName().c_str();
334 
335  if (lineNo > 0)
336  {
337  os << " at line " << lineNo << '.';
338  }
339  }
340  }
341 }
342 
343 
344 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
345 
347 {
348  err.write(os);
349 
350  return os;
351 }
352 
353 
354 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
355 // Global error definitions
356 
357 Foam::error Foam::FatalError("--> FOAM FATAL ERROR: ");
358 
359 
360 // ************************************************************************* //
Foam::JobInfo::exit
void exit()
End with "termination=exit".
Definition: JobInfo.C:172
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::foamVersion::patched
bool patched()
Foam::messageStream
Class to handle messaging in a simple, consistent stream-based manner.
Definition: messageStream.H:71
Foam::UPstream::parRun
static bool & parRun()
Test if this a parallel run, or allow modify access.
Definition: UPstream.H:434
Foam::messageStream::level
static int level
The output level (verbosity) of messages.
Definition: messageStream.H:107
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:350
Foam::string
A class for handling character strings derived from std::string.
Definition: string.H:73
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:83
error.H
fileName.H
Switch.H
Foam::OSstream
Generic output stream using a standard (STL) stream.
Definition: OSstream.H:54
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:121
Foam::IOstream::bad
bool bad() const
Return true if stream is corrupted.
Definition: IOstream.H:242
Pstream.H
Foam::error::message
string message() const
The accumulated error message.
Definition: error.C:277
Foam::error::useAbort
static bool useAbort()
True if FOAM_ABORT is on.
Definition: error.C:74
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:289
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:121
Foam::Perr
prefixOSstream Perr
OSstream wrapped stderr (std::cerr) with parallel prefix.
Foam::error::warnAboutAge
static void warnAboutAge(const char *what, const int version)
Emit warning on stderr about something being old.
Definition: error.C:41
Foam::nl
constexpr char nl
Definition: Ostream.H:385
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:80
Foam::error::abort
void abort()
Abort : used to stop code for fatal errors.
Definition: error.C:295
Foam::OStringStream
Output to string buffer, using a OSstream.
Definition: StringStream.H:196
dictionary.H
Foam::error::clear
void clear() const
Clear any messages.
Definition: error.C:283
JobInfo.H
Foam::dictionary::add
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:708
Foam::error::write
void write(Ostream &os, const bool includeTitle=true) const
Print error message.
Definition: error.C:301
Foam::JobInfo::abort
void abort()
End with "termination=abort".
Definition: JobInfo.C:178
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::error
Class to handle errors and exceptions in a simple, consistent stream-based manner.
Definition: error.H:70
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