Commit 181e27a9 authored by Mark Olesen's avatar Mark Olesen
Browse files

ENH: improve abort/exception handling in error class (#1780)

- previously setting FOAM_ABORT would preempt checks for throwing
  exceptions.

  Now check for throwing first, to allow try/catch code to do its job.
  However, ignore exception throwing for abort(). These are used
  infrequently in the code, but indicate that recovery is deemed
  impossible.

STYLE: use unique_ptr for internal stream buffer management
parent 707b29bb
...@@ -170,14 +170,14 @@ Foam::IOerror::operator Foam::dictionary() const ...@@ -170,14 +170,14 @@ Foam::IOerror::operator Foam::dictionary() const
} }
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::IOerror::exitOrAbort(const int, const bool isAbort) void Foam::IOerror::exitOrAbort(const int errNo, const bool isAbort)
{ {
if (!throwExceptions_ && JobInfo::constructed) if (!throwing_ && JobInfo::constructed)
{ {
jobInfo.add("FatalIOError", operator dictionary()); jobInfo.add("FatalIOError", operator dictionary());
if (isAbort) if (isAbort || hasEnv("FOAM_ABORT"))
{ {
jobInfo.abort(); jobInfo.abort();
} }
...@@ -187,14 +187,7 @@ void Foam::IOerror::exitOrAbort(const int, const bool isAbort) ...@@ -187,14 +187,7 @@ void Foam::IOerror::exitOrAbort(const int, const bool isAbort)
} }
} }
if (hasEnv("FOAM_ABORT")) if (throwing_ && !isAbort)
{
Perr<< nl << *this << nl
<< "\nFOAM aborting (FOAM_ABORT set)\n" << endl;
printStack(Perr);
std::abort();
}
else if (throwExceptions_)
{ {
// Make a copy of the error to throw // Make a copy of the error to throw
IOerror errorException(*this); IOerror errorException(*this);
...@@ -204,20 +197,27 @@ void Foam::IOerror::exitOrAbort(const int, const bool isAbort) ...@@ -204,20 +197,27 @@ void Foam::IOerror::exitOrAbort(const int, const bool isAbort)
throw errorException; throw errorException;
} }
else if (hasEnv("FOAM_ABORT"))
{
Perr<< nl << *this << nl
<< "\nFOAM aborting (FOAM_ABORT set)\n" << endl;
error::printStack(Perr);
std::abort();
}
else if (Pstream::parRun()) else if (Pstream::parRun())
{ {
if (isAbort) if (isAbort)
{ {
Perr<< nl << *this << nl Perr<< nl << *this << nl
<< "\nFOAM parallel run aborting\n" << endl; << "\nFOAM parallel run aborting\n" << endl;
printStack(Perr); error::printStack(Perr);
Pstream::abort(); Pstream::abort();
} }
else else
{ {
Perr<< nl << *this << nl Perr<< nl << *this << nl
<< "\nFOAM parallel run exiting\n" << endl; << "\nFOAM parallel run exiting\n" << endl;
Pstream::exit(1); Pstream::exit(errNo);
} }
} }
else else
...@@ -226,7 +226,7 @@ void Foam::IOerror::exitOrAbort(const int, const bool isAbort) ...@@ -226,7 +226,7 @@ void Foam::IOerror::exitOrAbort(const int, const bool isAbort)
{ {
Perr<< nl << *this << nl Perr<< nl << *this << nl
<< "\nFOAM aborting\n" << endl; << "\nFOAM aborting\n" << endl;
printStack(Perr); error::printStack(Perr);
#ifdef _WIN32 #ifdef _WIN32
std::exit(1); // Prefer exit() to avoid unnecessary warnings std::exit(1); // Prefer exit() to avoid unnecessary warnings
...@@ -238,15 +238,17 @@ void Foam::IOerror::exitOrAbort(const int, const bool isAbort) ...@@ -238,15 +238,17 @@ void Foam::IOerror::exitOrAbort(const int, const bool isAbort)
{ {
Perr<< nl << *this << nl Perr<< nl << *this << nl
<< "\nFOAM exiting\n" << endl; << "\nFOAM exiting\n" << endl;
std::exit(1); std::exit(errNo);
} }
} }
} }
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::IOerror::exit(const int) void Foam::IOerror::exit(const int)
{ {
exitOrAbort(1, hasEnv("FOAM_ABORT")); exitOrAbort(1, false);
} }
......
...@@ -79,17 +79,9 @@ Foam::error::error(const string& title) ...@@ -79,17 +79,9 @@ Foam::error::error(const string& title)
functionName_("unknown"), functionName_("unknown"),
sourceFileName_("unknown"), sourceFileName_("unknown"),
sourceFileLineNumber_(0), sourceFileLineNumber_(0),
throwExceptions_(false), throwing_(false),
messageStreamPtr_(new OStringStream()) messageStreamPtr_(new OStringStream())
{ {}
if (!messageStreamPtr_->good())
{
Perr<< nl
<< "error::error(const string&) : cannot open error stream"
<< endl;
exit(1);
}
}
Foam::error::error(const dictionary& errDict) Foam::error::error(const dictionary& errDict)
...@@ -99,17 +91,9 @@ Foam::error::error(const dictionary& errDict) ...@@ -99,17 +91,9 @@ Foam::error::error(const dictionary& errDict)
functionName_(errDict.get<string>("functionName")), functionName_(errDict.get<string>("functionName")),
sourceFileName_(errDict.get<string>("sourceFileName")), sourceFileName_(errDict.get<string>("sourceFileName")),
sourceFileLineNumber_(errDict.get<label>("sourceFileLineNumber")), sourceFileLineNumber_(errDict.get<label>("sourceFileLineNumber")),
throwExceptions_(false), throwing_(false),
messageStreamPtr_(new OStringStream()) messageStreamPtr_(new OStringStream())
{ {}
if (!messageStreamPtr_->good())
{
Perr<< nl
<< "error::error(const dictionary&) : cannot open error stream"
<< endl;
exit(1);
}
}
Foam::error::error(const error& err) Foam::error::error(const error& err)
...@@ -119,7 +103,7 @@ Foam::error::error(const error& err) ...@@ -119,7 +103,7 @@ Foam::error::error(const error& err)
functionName_(err.functionName_), functionName_(err.functionName_),
sourceFileName_(err.sourceFileName_), sourceFileName_(err.sourceFileName_),
sourceFileLineNumber_(err.sourceFileLineNumber_), sourceFileLineNumber_(err.sourceFileLineNumber_),
throwExceptions_(err.throwExceptions_), throwing_(err.throwing_),
messageStreamPtr_(new OStringStream(*err.messageStreamPtr_)) messageStreamPtr_(new OStringStream(*err.messageStreamPtr_))
{} {}
...@@ -127,9 +111,7 @@ Foam::error::error(const error& err) ...@@ -127,9 +111,7 @@ Foam::error::error(const error& err)
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::error::~error() noexcept Foam::error::~error() noexcept
{ {}
delete messageStreamPtr_;
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
...@@ -208,27 +190,14 @@ Foam::error::operator Foam::dictionary() const ...@@ -208,27 +190,14 @@ Foam::error::operator Foam::dictionary() const
return errDict; return errDict;
} }
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::string Foam::error::message() const
{
return messageStreamPtr_->str();
}
void Foam::error::clear() const
{
return messageStreamPtr_->reset();
}
void Foam::error::exitOrAbort(const int errNo, const bool isAbort) void Foam::error::exitOrAbort(const int errNo, const bool isAbort)
{ {
if (!throwExceptions_ && JobInfo::constructed) if (!throwing_ && JobInfo::constructed)
{ {
jobInfo.add("FatalError", operator dictionary()); jobInfo.add("FatalError", operator dictionary());
if (isAbort) if (isAbort || hasEnv("FOAM_ABORT"))
{ {
jobInfo.abort(); jobInfo.abort();
} }
...@@ -238,14 +207,7 @@ void Foam::error::exitOrAbort(const int errNo, const bool isAbort) ...@@ -238,14 +207,7 @@ void Foam::error::exitOrAbort(const int errNo, const bool isAbort)
} }
} }
if (hasEnv("FOAM_ABORT")) if (throwing_ && !isAbort)
{
Perr<< nl << *this << nl
<< "\nFOAM aborting (FOAM_ABORT set)\n" << endl;
printStack(Perr);
std::abort();
}
else if (throwExceptions_)
{ {
// Make a copy of the error to throw // Make a copy of the error to throw
error errorException(*this); error errorException(*this);
...@@ -255,13 +217,20 @@ void Foam::error::exitOrAbort(const int errNo, const bool isAbort) ...@@ -255,13 +217,20 @@ void Foam::error::exitOrAbort(const int errNo, const bool isAbort)
throw errorException; throw errorException;
} }
else if (hasEnv("FOAM_ABORT"))
{
Perr<< nl << *this << nl
<< "\nFOAM aborting (FOAM_ABORT set)\n" << endl;
error::printStack(Perr);
std::abort();
}
else if (Pstream::parRun()) else if (Pstream::parRun())
{ {
if (isAbort) if (isAbort)
{ {
Perr<< nl << *this << nl Perr<< nl << *this << nl
<< "\nFOAM parallel run aborting\n" << endl; << "\nFOAM parallel run aborting\n" << endl;
printStack(Perr); error::printStack(Perr);
Pstream::abort(); Pstream::abort();
} }
else else
...@@ -277,7 +246,7 @@ void Foam::error::exitOrAbort(const int errNo, const bool isAbort) ...@@ -277,7 +246,7 @@ void Foam::error::exitOrAbort(const int errNo, const bool isAbort)
{ {
Perr<< nl << *this << nl Perr<< nl << *this << nl
<< "\nFOAM aborting\n" << endl; << "\nFOAM aborting\n" << endl;
printStack(Perr); error::printStack(Perr);
#ifdef _WIN32 #ifdef _WIN32
std::exit(1); // Prefer exit() to avoid unnecessary warnings std::exit(1); // Prefer exit() to avoid unnecessary warnings
...@@ -295,9 +264,23 @@ void Foam::error::exitOrAbort(const int errNo, const bool isAbort) ...@@ -295,9 +264,23 @@ void Foam::error::exitOrAbort(const int errNo, const bool isAbort)
} }
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::string Foam::error::message() const
{
return messageStreamPtr_->str();
}
void Foam::error::clear() const
{
return messageStreamPtr_->reset();
}
void Foam::error::exit(const int errNo) void Foam::error::exit(const int errNo)
{ {
exitOrAbort(errNo, hasEnv("FOAM_ABORT")); exitOrAbort(errNo, false);
} }
......
...@@ -45,6 +45,11 @@ Usage ...@@ -45,6 +45,11 @@ Usage
SourceFiles SourceFiles
error.C error.C
IOerror.C
SeeAlso
Foam::errorManip
Foam::errorManipArg
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
...@@ -52,6 +57,7 @@ SourceFiles ...@@ -52,6 +57,7 @@ SourceFiles
#define error_H #define error_H
#include "messageStream.H" #include "messageStream.H"
#include <memory>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
...@@ -80,8 +86,8 @@ protected: ...@@ -80,8 +86,8 @@ protected:
string functionName_; string functionName_;
string sourceFileName_; string sourceFileName_;
label sourceFileLineNumber_; label sourceFileLineNumber_;
bool throwExceptions_; bool throwing_;
OStringStream* messageStreamPtr_; std::unique_ptr<OStringStream> messageStreamPtr_;
public: public:
...@@ -138,15 +144,15 @@ public: ...@@ -138,15 +144,15 @@ public:
//- Return the current exception throwing (on or off) //- Return the current exception throwing (on or off)
bool throwing() const bool throwing() const
{ {
return throwExceptions_; return throwing_;
} }
//- Activate/deactivate exception throwing //- Activate/deactivate exception throwing
// \return the previous throwing state // \return the previous throwing state
inline bool throwExceptions(bool doThrow) inline bool throwExceptions(bool doThrow)
{ {
const bool prev = throwExceptions_; const bool prev = throwing_;
throwExceptions_ = doThrow; throwing_ = doThrow;
return prev; return prev;
} }
......
...@@ -135,17 +135,17 @@ exit(error& err, const int errNo = 1) ...@@ -135,17 +135,17 @@ exit(error& err, const int errNo = 1)
} }
inline errorManip<error> inline errorManipArg<IOerror, int>
abort(error& err) exit(IOerror& err, const int errNo = 1)
{ {
return errorManip<error>(&error::abort, err); return errorManipArg<IOerror, int>(&IOerror::exit, err, errNo);
} }
inline errorManipArg<IOerror, int> inline errorManip<error>
exit(IOerror& err, const int errNo = 1) abort(error& err)
{ {
return errorManipArg<IOerror, int>(&IOerror::exit, err, errNo); return errorManip<error>(&error::abort, err);
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment