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 
38 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
39 
40 void Foam::error::warnAboutAge(const char* what, const int version)
41 {
42  if (version <= 0)
43  {
44  // No warning for 0 (unversioned) or -ve values (silent versioning)
45  }
46  else if (version < 1000)
47  {
48  // Warning for things that predate the YYMM versioning
49  // (eg, 240 for version 2.4)
50  std::cerr
51  << " This " << what << " is considered to be VERY old!\n"
52  << std::endl;
53  }
54  else if (version < foamVersion::api)
55  {
56  const int months =
57  (
58  // YYMM -> months
59  (12 * (foamVersion::api/100) + (foamVersion::api % 100))
60  - (12 * (version/100) + (version % 100))
61  );
62 
63  std::cerr
64  << " This " << what << " is deemed to be " << months
65  << " months old.\n"
66  << std::endl;
67  }
68  // No warning for (foamVersion::api < version).
69  // We use this to denote future expiry dates of transition features.
70 }
71 
72 
73 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
74 
75 Foam::error::error(const string& title)
76 :
77  std::exception(),
78  messageStream(title, messageStream::FATAL),
79  functionName_("unknown"),
80  sourceFileName_("unknown"),
81  sourceFileLineNumber_(0),
82  throwExceptions_(false),
83  messageStreamPtr_(new OStringStream())
84 {
85  if (!messageStreamPtr_->good())
86  {
87  Perr<< nl
88  << "error::error(const string&) : cannot open error stream"
89  << endl;
90  exit(1);
91  }
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  throwExceptions_(false),
103  messageStreamPtr_(new OStringStream())
104 {
105  if (!messageStreamPtr_->good())
106  {
107  Perr<< nl
108  << "error::error(const dictionary&) : cannot open error stream"
109  << endl;
110  exit(1);
111  }
112 }
113 
114 
116 :
117  std::exception(),
118  messageStream(err),
119  functionName_(err.functionName_),
120  sourceFileName_(err.sourceFileName_),
121  sourceFileLineNumber_(err.sourceFileLineNumber_),
122  throwExceptions_(err.throwExceptions_),
123  messageStreamPtr_(new OStringStream(*err.messageStreamPtr_))
124 {}
125 
126 
127 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
128 
130 {
131  delete messageStreamPtr_;
132 }
133 
134 
135 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
136 
137 Foam::OSstream& Foam::error::operator()
138 (
139  const string& functionName
140 )
141 {
142  functionName_ = functionName;
143  sourceFileName_.clear();
144  sourceFileLineNumber_ = -1;
145 
146  return operator OSstream&();
147 }
148 
149 
150 Foam::OSstream& Foam::error::operator()
151 (
152  const char* functionName,
153  const char* sourceFileName,
154  const int sourceFileLineNumber
155 )
156 {
157  functionName_ = functionName;
158  sourceFileName_ = sourceFileName;
159  sourceFileLineNumber_ = sourceFileLineNumber;
160 
161  return operator OSstream&();
162 }
163 
164 
165 Foam::OSstream& Foam::error::operator()
166 (
167  const string& functionName,
168  const char* sourceFileName,
169  const int sourceFileLineNumber
170 )
171 {
172  return operator()
173  (
174  functionName.c_str(),
175  sourceFileName,
176  sourceFileLineNumber
177  );
178 }
179 
180 
181 Foam::error::operator Foam::OSstream&()
182 {
183  if (!messageStreamPtr_->good())
184  {
185  Perr<< nl
186  << "error::operator OSstream&() : error stream has failed"
187  << endl;
188  abort();
189  }
190 
191  return *messageStreamPtr_;
192 }
193 
194 
195 Foam::error::operator Foam::dictionary() const
196 {
197  dictionary errDict;
198 
199  string oneLineMessage(message());
200  oneLineMessage.replaceAll("\n", " ");
201 
202  errDict.add("type", word("Foam::error"));
203  errDict.add("message", oneLineMessage);
204  errDict.add("function", functionName());
205  errDict.add("sourceFile", sourceFileName());
206  errDict.add("sourceFileLineNumber", sourceFileLineNumber());
207 
208  return errDict;
209 }
210 
211 
212 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
213 
215 {
216  return messageStreamPtr_->str();
217 }
218 
219 
220 void Foam::error::clear() const
221 {
222  return messageStreamPtr_->reset();
223 }
224 
225 
226 void Foam::error::exitOrAbort(const int errNo, const bool isAbort)
227 {
228  if (!throwExceptions_ && JobInfo::constructed)
229  {
230  jobInfo.add("FatalError", operator dictionary());
231  if (isAbort)
232  {
233  jobInfo.abort();
234  }
235  else
236  {
237  jobInfo.exit();
238  }
239  }
240 
241  if (hasEnv("FOAM_ABORT"))
242  {
243  Perr<< nl << *this << nl
244  << "\nFOAM aborting (FOAM_ABORT set)\n" << endl;
245  printStack(Perr);
246  std::abort();
247  }
248  else if (throwExceptions_)
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  }
258  else if (Pstream::parRun())
259  {
260  if (isAbort)
261  {
262  Perr<< nl << *this << nl
263  << "\nFOAM parallel run aborting\n" << endl;
264  printStack(Perr);
265  Pstream::abort();
266  }
267  else
268  {
269  Perr<< nl << *this << nl
270  << "\nFOAM parallel run exiting\n" << endl;
271  Pstream::exit(errNo);
272  }
273  }
274  else
275  {
276  if (isAbort)
277  {
278  Perr<< nl << *this << nl
279  << "\nFOAM aborting\n" << endl;
280  printStack(Perr);
281 
282  #ifdef _WIN32
283  std::exit(1); // Prefer exit() to avoid unnecessary warnings
284  #else
285  std::abort();
286  #endif
287  }
288  else
289  {
290  Perr<< nl << *this << nl
291  << "\nFOAM exiting\n" << endl;
292  std::exit(errNo);
293  }
294  }
295 }
296 
297 
298 void Foam::error::exit(const int errNo)
299 {
300  exitOrAbort(errNo, hasEnv("FOAM_ABORT"));
301 }
302 
303 
305 {
306  exitOrAbort(1, true);
307 }
308 
309 
310 void Foam::error::write(Ostream& os, const bool includeTitle) const
311 {
312  if (os.bad())
313  {
314  return;
315  }
316 
317  os << nl;
318  if (includeTitle && !title().empty())
319  {
320  os << title().c_str() << nl;
321  }
322  os << message().c_str();
323 
324 
325  const label lineNo = sourceFileLineNumber();
326 
327  if (error::level >= 2 && lineNo && !functionName().empty())
328  {
329  os << nl << nl
330  << " From " << functionName().c_str() << nl;
331 
332  if (!sourceFileName().empty())
333  {
334  os << " in file " << sourceFileName().c_str();
335 
336  if (lineNo > 0)
337  {
338  os << " at line " << lineNo << '.';
339  }
340  }
341  }
342 }
343 
344 
345 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
346 
348 {
349  err.write(os);
350 
351  return os;
352 }
353 
354 
355 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
356 // Global error definitions
357 
358 Foam::error Foam::FatalError("--> FOAM FATAL ERROR: ");
359 
360 
361 // ************************************************************************* //
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::messageStream
Class to handle messaging in a simple, consistent stream-based manner.
Definition: messageStream.H:71
Foam::UPstream::parRun
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:415
Foam::messageStream::level
static int level
Control the output verbosity of messageStream.
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::operator<<
Ostream & operator<<(Ostream &, const boundaryPatch &p)
Write boundaryPatch as dictionary entries (without surrounding braces)
Definition: boundaryPatch.C:83
Foam::hasEnv
bool hasEnv(const std::string &envName)
True if environment variable of given name is defined.
Definition: MSwindows.C:363
Foam::foamVersion::api
const int api
Foam::error::error
error(const string &title)
Construct from title string.
Definition: error.C:75
error.H
fileName.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:214
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:137
Foam::error::exit
void exit(const int errNo=1)
Exit : can be called for any error to exit program.
Definition: error.C:298
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:129
Foam::Perr
prefixOSstream Perr
An Ostream wrapper for parallel output to std::cerr.
Foam::error::warnAboutAge
static void warnAboutAge(const char *what, const int version)
Emit warning on stderr about something being old.
Definition: error.C:40
Foam::nl
constexpr char nl
Definition: Ostream.H:385
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:304
Foam::OStringStream
Output to string buffer, using a OSstream.
Definition: StringStream.H:196
Foam::error::messageStreamPtr_
OStringStream * messageStreamPtr_
Definition: error.H:83
dictionary.H
Foam::error::clear
void clear() const
Clear any messages.
Definition: error.C:220
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:310
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::IOstream::good
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:224
Foam::error
Class to handle errors and exceptions in a simple, consistent stream-based manner.
Definition: error.H:64
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