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

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