ENH: simplify exit/abort handling and jobinfo (code reduction)

- handle failures more robustly
- add static shutdown() for similarity with Pstream etc.
This commit is contained in:
Mark Olesen
2021-07-01 14:16:46 +02:00
parent 8a1f667067
commit cc5aa20931
19 changed files with 349 additions and 267 deletions

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd. Copyright (C) 2020-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -37,10 +37,13 @@ using namespace Foam;
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
#if 0 argList::addBoolOption("no-throw", "Use error, no exceptions");
argList::addBoolOption("ioerror", "Use IOerror instead");
argList::noBanner(); argList::noBanner();
argList args(argc, argv); argList args(argc, argv);
#if 0
if (true) if (true)
{ {
InfoErr<< "Called with " << (args.size()-1) << " args\n"; InfoErr<< "Called with " << (args.size()-1) << " args\n";
@ -49,7 +52,13 @@ int main(int argc, char *argv[])
} }
#endif #endif
const bool useIOerr = args.found("ioerror");
if (!args.found("no-throw"))
{
FatalIOError.throwExceptions();
FatalError.throwExceptions(); FatalError.throwExceptions();
}
try try
{ {
@ -60,17 +69,34 @@ int main(int argc, char *argv[])
IOWarningInFunction(dict) << "warning 3" << endl; IOWarningInFunction(dict) << "warning 3" << endl;
if (useIOerr)
{
FatalIOErrorInFunction(dict)
<< "This is an error from 1" << nl
<< "Explanation to follow:" << endl;
FatalIOError
<< "Error 2"
<< exit(FatalIOError);
}
else
{
FatalErrorInFunction FatalErrorInFunction
<< "This is an error from 1" << nl << "This is an error from 1" << nl
<< "Explanation to follow:" << endl; << "Explanation to follow:" << endl;
FatalErrorInFunction FatalError
<< "Error 2" << "Error 2"
<< exit(FatalError); << exit(FatalError);
} }
}
catch (const Foam::IOerror& err)
{
Serr<< "Caught IO error " << err << nl << endl;
}
catch (const Foam::error& err) catch (const Foam::error& err)
{ {
Serr<< "Caught Foam error " << err << nl << endl; Serr<< "Caught error " << err << nl << endl;
} }
try try
@ -79,9 +105,13 @@ int main(int argc, char *argv[])
<< "Error# 3" << "Error# 3"
<< exit(FatalError); << exit(FatalError);
} }
catch (const Foam::IOerror& err)
{
Serr<< "Caught IO error " << err << nl << endl;
}
catch (const Foam::error& err) catch (const Foam::error& err)
{ {
Serr<< "Caught Foam error " << err << nl << endl; Serr<< "Caught error " << err << nl << endl;
} }
return 0; return 0;

View File

@ -7,7 +7,7 @@
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2011 Symscape Copyright (C) 2011 Symscape
Copyright (C) 2016-2020 OpenCFD Ltd. Copyright (C) 2016-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -87,7 +87,7 @@ void Foam::sigFpe::sigHandler(int)
{ {
resetHandler("SIGFPE", SIGFPE); resetHandler("SIGFPE", SIGFPE);
jobInfo.signalEnd(); // Update jobInfo file JobInfo::shutdown(); // From running -> finished
error::printStack(Perr); error::printStack(Perr);
clearFpe(); clearFpe();
::raise(SIGFPE); // Throw signal (to old handler) ::raise(SIGFPE); // Throw signal (to old handler)

View File

@ -7,7 +7,7 @@
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2011 Symscape Copyright (C) 2011 Symscape
Copyright (C) 2018-2019 OpenCFD Ltd. Copyright (C) 2018-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -47,7 +47,7 @@ void Foam::sigInt::sigHandler(int)
{ {
resetHandler("SIGINT", SIGINT); resetHandler("SIGINT", SIGINT);
jobInfo.signalEnd(); // Update jobInfo file JobInfo::shutdown(); // From running -> finished
::raise(SIGINT); // Throw signal (to old handler) ::raise(SIGINT); // Throw signal (to old handler)
} }

View File

@ -7,7 +7,7 @@
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2011 Symscape Copyright (C) 2011 Symscape
Copyright (C) 2018-2019 OpenCFD Ltd. Copyright (C) 2018-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -49,7 +49,7 @@ void Foam::sigQuit::sigHandler(int)
{ {
resetHandler("SIGBREAK", SIGBREAK); resetHandler("SIGBREAK", SIGBREAK);
jobInfo.signalEnd(); // Update jobInfo file JobInfo::shutdown(); // From running -> finished
error::printStack(Perr); error::printStack(Perr);
::raise(SIGBREAK); // Throw signal (to old handler) ::raise(SIGBREAK); // Throw signal (to old handler)
} }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2018-2019 OpenCFD Ltd. Copyright (C) 2018-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -46,7 +46,7 @@ void Foam::sigSegv::sigHandler(int)
{ {
resetHandler("SIGSEGV", SIGSEGV); resetHandler("SIGSEGV", SIGSEGV);
jobInfo.signalEnd(); // Update jobInfo file JobInfo::shutdown(); // From running -> finished
error::printStack(Perr); error::printStack(Perr);
::raise(SIGSEGV); // Throw signal (to old handler) ::raise(SIGSEGV); // Throw signal (to old handler)
} }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2016-2019 OpenCFD Ltd. Copyright (C) 2016-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -95,7 +95,7 @@ void Foam::sigStopAtWriteNow::sigHandler(int)
{ {
resetHandler("stopAtWriteNow", signal_); resetHandler("stopAtWriteNow", signal_);
jobInfo.signalEnd(); // Update jobInfo file JobInfo::shutdown(); // From running -> finished
if (runTimePtr_) if (runTimePtr_)
{ {

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2016-2020 OpenCFD Ltd. Copyright (C) 2016-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -121,7 +121,7 @@ void Foam::sigFpe::sigHandler(int)
resetHandler("SIGFPE", SIGFPE); resetHandler("SIGFPE", SIGFPE);
jobInfo.signalEnd(); // Update jobInfo file JobInfo::shutdown(); // From running -> finished
error::printStack(Perr); error::printStack(Perr);
::raise(SIGFPE); // Throw signal (to old handler) ::raise(SIGFPE); // Throw signal (to old handler)

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2018-2019 OpenCFD Ltd. Copyright (C) 2018-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -46,7 +46,7 @@ void Foam::sigInt::sigHandler(int)
{ {
resetHandler("SIGINT", SIGINT); resetHandler("SIGINT", SIGINT);
jobInfo.signalEnd(); // Update jobInfo file JobInfo::shutdown(); // From running -> finished
::raise(SIGINT); // Throw signal (to old handler) ::raise(SIGINT); // Throw signal (to old handler)
} }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2017-2019 OpenCFD Ltd. Copyright (C) 2017-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -46,7 +46,7 @@ void Foam::sigQuit::sigHandler(int)
{ {
resetHandler("SIGQUIT", SIGQUIT); resetHandler("SIGQUIT", SIGQUIT);
jobInfo.signalEnd(); // Update jobInfo file JobInfo::shutdown(); // From running -> finished
error::printStack(Perr); error::printStack(Perr);
::raise(SIGQUIT); // Throw signal (to old handler) ::raise(SIGQUIT); // Throw signal (to old handler)
} }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2018-2019 OpenCFD Ltd. Copyright (C) 2018-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -46,7 +46,7 @@ void Foam::sigSegv::sigHandler(int)
{ {
resetHandler("SIGSEGV", SIGSEGV); resetHandler("SIGSEGV", SIGSEGV);
jobInfo.signalEnd(); // Update jobInfo file JobInfo::shutdown(); // From running -> finished
error::printStack(Perr); error::printStack(Perr);
::raise(SIGSEGV); // Throw signal (to old handler) ::raise(SIGSEGV); // Throw signal (to old handler)
} }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2016-2019 OpenCFD Ltd. Copyright (C) 2016-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -97,7 +97,7 @@ void Foam::sigStopAtWriteNow::sigHandler(int)
{ {
resetHandler("stopAtWriteNow", signal_); resetHandler("stopAtWriteNow", signal_);
jobInfo.signalEnd(); // Update jobInfo file JobInfo::shutdown(); // From running -> finished
if (runTimePtr_) if (runTimePtr_)
{ {

View File

@ -2,6 +2,7 @@ global/foamConfig.Cver
global/globals.C global/globals.C
/* global/constants/constants.C in globals.C */ /* global/constants/constants.C in globals.C */
/* global/constants/dimensionedConstants.C in globals.C */ /* global/constants/dimensionedConstants.C in globals.C */
/* global/JobInfo/JobInfo.C in globals.C */
global/argList/argList.C global/argList/argList.C
global/argList/argListHelp.C global/argList/argListHelp.C
global/clock/clock.C global/clock/clock.C

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2015-2020 OpenCFD Ltd. Copyright (C) 2015-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -159,9 +159,7 @@ Foam::IOerror::operator Foam::dictionary() const
{ {
dictionary errDict(error::operator dictionary()); dictionary errDict(error::operator dictionary());
errDict.remove("type"); errDict.add("type", word("Foam::IOerror"), true); // overwrite
errDict.add("type", word("Foam::IOerror"));
errDict.add("ioFileName", ioFileName()); errDict.add("ioFileName", ioFileName());
errDict.add("ioStartLineNumber", ioStartLineNumber()); errDict.add("ioStartLineNumber", ioStartLineNumber());
errDict.add("ioEndLineNumber", ioEndLineNumber()); errDict.add("ioEndLineNumber", ioEndLineNumber());
@ -172,22 +170,11 @@ Foam::IOerror::operator Foam::dictionary() const
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::IOerror::exitOrAbort(const int errNo, const bool isAbort) void Foam::IOerror::exiting(const int errNo, const bool isAbort)
{ {
if (!throwing_ && JobInfo::constructed) if (throwing_)
{ {
jobInfo.add("FatalIOError", operator dictionary()); if (!isAbort)
if (isAbort || error::useAbort())
{
jobInfo.abort();
}
else
{
jobInfo.exit();
}
}
if (throwing_ && !isAbort)
{ {
// Make a copy of the error to throw // Make a copy of the error to throw
IOerror errorException(*this); IOerror errorException(*this);
@ -196,51 +183,16 @@ void Foam::IOerror::exitOrAbort(const int errNo, const bool isAbort)
messageStreamPtr_->reset(); messageStreamPtr_->reset();
throw errorException; throw errorException;
} return;
else if (error::useAbort())
{
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;
error::printStack(Perr);
Pstream::abort();
}
else
{
Perr<< nl << *this << nl
<< "\nFOAM parallel run exiting\n" << endl;
Pstream::exit(errNo);
} }
} }
else else if (JobInfo::constructed)
{ {
if (isAbort) jobInfo.add("FatalIOError", operator dictionary());
{ JobInfo::shutdown(isAbort || error::useAbort());
Perr<< nl << *this << nl }
<< "\nFOAM aborting\n" << endl;
error::printStack(Perr);
#ifdef _WIN32 simpleExit(errNo, isAbort);
std::exit(1); // Prefer exit() to avoid unnecessary warnings
#else
std::abort();
#endif
}
else
{
Perr<< nl << *this << nl
<< "\nFOAM exiting\n" << endl;
std::exit(errNo);
}
}
} }
@ -248,13 +200,13 @@ void Foam::IOerror::exitOrAbort(const int errNo, const bool isAbort)
void Foam::IOerror::exit(const int) void Foam::IOerror::exit(const int)
{ {
exitOrAbort(1, false); exiting(1, false);
} }
void Foam::IOerror::abort() void Foam::IOerror::abort()
{ {
exitOrAbort(1, true); exiting(1, true);
} }
@ -323,7 +275,6 @@ void Foam::IOerror::write(Ostream& os, const bool includeTitle) const
Foam::Ostream& Foam::operator<<(Ostream& os, const IOerror& err) Foam::Ostream& Foam::operator<<(Ostream& os, const IOerror& err)
{ {
err.write(os); err.write(os);
return os; return os;
} }

View File

@ -199,22 +199,11 @@ Foam::error::operator Foam::dictionary() const
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::error::exitOrAbort(const int errNo, const bool isAbort) void Foam::error::exiting(const int errNo, const bool isAbort)
{ {
if (!throwing_ && JobInfo::constructed) if (throwing_)
{ {
jobInfo.add("FatalError", operator dictionary()); if (!isAbort)
if (isAbort || error::useAbort())
{
jobInfo.abort();
}
else
{
jobInfo.exit();
}
}
if (throwing_ && !isAbort)
{ {
// Make a copy of the error to throw // Make a copy of the error to throw
error errorException(*this); error errorException(*this);
@ -223,8 +212,24 @@ void Foam::error::exitOrAbort(const int errNo, const bool isAbort)
messageStreamPtr_->reset(); messageStreamPtr_->reset();
throw errorException; throw errorException;
return;
} }
else if (error::useAbort()) }
else if (JobInfo::constructed)
{
jobInfo.add("FatalError", operator dictionary());
JobInfo::shutdown(isAbort || error::useAbort());
}
simpleExit(errNo, isAbort);
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void Foam::error::simpleExit(const int errNo, const bool isAbort)
{
if (error::useAbort())
{ {
Perr<< nl << *this << nl Perr<< nl << *this << nl
<< "\nFOAM aborting (FOAM_ABORT set)\n" << endl; << "\nFOAM aborting (FOAM_ABORT set)\n" << endl;
@ -287,13 +292,13 @@ void Foam::error::clear() const
void Foam::error::exit(const int errNo) void Foam::error::exit(const int errNo)
{ {
exitOrAbort(errNo, false); exiting(errNo, false);
} }
void Foam::error::abort() void Foam::error::abort()
{ {
exitOrAbort(1, true); exiting(1, true);
} }
@ -345,7 +350,6 @@ void Foam::error::write(Ostream& os, const bool includeTitle) const
Foam::Ostream& Foam::operator<<(Ostream& os, const error& err) Foam::Ostream& Foam::operator<<(Ostream& os, const error& err)
{ {
err.write(os); err.write(os);
return os; return os;
} }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2015-2020 OpenCFD Ltd. Copyright (C) 2015-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -75,8 +75,8 @@ class error
{ {
// Private Member Functions // Private Member Functions
//- Common code for exit or abort //- Exit or abort code, with exception and jobinfo handling
void exitOrAbort(const int errNo, const bool isAbort); void exiting(const int errNo, const bool isAbort);
protected: protected:
@ -90,6 +90,12 @@ protected:
std::unique_ptr<OStringStream> messageStreamPtr_; std::unique_ptr<OStringStream> messageStreamPtr_;
// Protected Member Functions
//- Exit or abort, without throwing or job control handling
void simpleExit(const int errNo, const bool isAbort);
public: public:
// Constructors // Constructors
@ -126,48 +132,34 @@ public:
//- Clear any messages //- Clear any messages
void clear() const; void clear() const;
const string& functionName() const const string& functionName() const noexcept
{ {
return functionName_; return functionName_;
} }
const string& sourceFileName() const const string& sourceFileName() const noexcept
{ {
return sourceFileName_; return sourceFileName_;
} }
label sourceFileLineNumber() const label sourceFileLineNumber() const noexcept
{ {
return sourceFileLineNumber_; return sourceFileLineNumber_;
} }
//- Return the current exception throwing (on or off) //- Return the current exception throwing state (on or off)
bool throwing() const bool throwing() const noexcept
{ {
return throwing_; return throwing_;
} }
//- Activate/deactivate exception throwing //- Specify exception throwing (default is activate)
// \return the previous throwing state // \return the previous throwing state
inline bool throwExceptions(bool doThrow) bool throwExceptions(bool doThrow = true) noexcept
{ {
const bool prev = throwing_; bool old = throwing_;
throwing_ = doThrow; throwing_ = doThrow;
return prev; return old;
}
//- Activate exception throwing
// \return the previous throwing state
inline bool throwExceptions()
{
return throwExceptions(true);
}
//- Deactivate exception throwing
// \return the previous throwing state
inline bool dontThrowExceptions()
{
return throwExceptions(false);
} }
//- Define basic print message //- Define basic print message
@ -204,7 +196,7 @@ public:
//- Convert to OSstream //- Convert to OSstream
operator OSstream&(); operator OSstream&();
//- Create and return a dictionary representation of the error //- Return a dictionary representation of the error
operator dictionary() const; operator dictionary() const;
@ -228,6 +220,16 @@ public:
//- Print error message //- Print error message
void write(Ostream& os, const bool includeTitle = true) const; void write(Ostream& os, const bool includeTitle = true) const;
// Housekeeping
//- Deactivate exception throwing
// \return the previous throwing state
bool dontThrowExceptions() noexcept
{
return throwExceptions(false);
}
}; };
@ -249,8 +251,8 @@ class IOerror
// Private Member Functions // Private Member Functions
//- Common code for exit or abort //- Exit or abort code, with exception and jobinfo handling
void exitOrAbort(const int errNo, const bool isAbort); void exiting(const int errNo, const bool isAbort);
public: public:
@ -270,17 +272,17 @@ public:
// Member Functions // Member Functions
const string& ioFileName() const const string& ioFileName() const noexcept
{ {
return ioFileName_; return ioFileName_;
} }
label ioStartLineNumber() const label ioStartLineNumber() const noexcept
{ {
return ioStartLineNumber_; return ioStartLineNumber_;
} }
label ioEndLineNumber() const label ioEndLineNumber() const noexcept
{ {
return ioEndLineNumber_; return ioEndLineNumber_;
} }
@ -329,7 +331,7 @@ public:
const string& msg const string& msg
); );
//- Create and return a dictionary representation of the error //- Return a dictionary representation of the error
operator dictionary() const; operator dictionary() const;

View File

@ -127,25 +127,27 @@ public:
explicit messageStream(const dictionary& dict); explicit messageStream(const dictionary& dict);
// Member functions // Member Functions
//- The title of this error type //- The title of this error type
const string& title() const const string& title() const noexcept
{ {
return title_; return title_;
} }
//- The maximum number of errors before program termination //- The maximum number of errors before program termination
int maxErrors() const int maxErrors() const noexcept
{ {
return maxErrors_; return maxErrors_;
} }
//- Non-const access to the maximum number of errors before //- Set the maximum number of errors before program termination
//- program termination to enable user to reset it // \return the previous value for maxErrors
int& maxErrors() int maxErrors(int nErrors) noexcept
{ {
return maxErrors_; int old = maxErrors_;
maxErrors_ = nErrors;
return old;
} }
//- Convert to OSstream //- Convert to OSstream

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2018 OpenCFD Ltd. Copyright (C) 2017-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -27,9 +27,9 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "JobInfo.H" #include "JobInfo.H"
#include "OSspecific.H"
#include "clock.H" #include "clock.H"
#include "OFstream.H" #include "OFstream.H"
#include "OSspecific.H"
#include "Pstream.H" #include "Pstream.H"
#include "foamVersion.H" #include "foamVersion.H"
@ -48,45 +48,115 @@ License
bool Foam::JobInfo::writeJobInfo(Foam::debug::infoSwitch("writeJobInfo", 0)); bool Foam::JobInfo::writeJobInfo(Foam::debug::infoSwitch("writeJobInfo", 0));
Foam::JobInfo Foam::jobInfo; Foam::JobInfo Foam::jobInfo;
// Foam::JobInfo::constructed defined in globals.C
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
bool Foam::JobInfo::write(Ostream& os) const // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam
{ {
if (writeJobInfo && Pstream::master())
// Ensure given directory exists (called on master only)
static inline bool ensureJobDirExists(const fileName& dir)
{
if (!Foam::isDir(dir) && !Foam::mkDir(dir))
{
std::cerr
<< "WARNING: no JobInfo directory: " << dir << nl
<< " disabling JobInfo" << nl;
return false;
}
return true;
}
// Write dictionary entries (called on master only)
static inline bool writeJobDict(Ostream& os, const dictionary& dict)
{ {
if (os.good()) if (os.good())
{ {
dictionary::write(os, false); dict.writeEntries(os, true); // With extraNewLine=true
return true; return true;
} }
return false;
}
} // End namespace Foam
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
void Foam::JobInfo::disable() noexcept
{
writeJobInfo = false;
}
void Foam::JobInfo::shutdown()
{
jobInfo.jobEnding();
}
void Foam::JobInfo::shutdown(bool isAbort)
{
if (isAbort)
{
jobInfo.jobEnding("abort");
}
else else
{ {
return false; jobInfo.jobEnding("exit");
} }
} }
return true;
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::JobInfo::end(const word& terminationType) void Foam::JobInfo::jobEnding()
{ {
if (writeJobInfo && constructed && Pstream::master()) if (!running_.empty())
{
if (!Foam::mv(running_, finished_))
{
Foam::rm(running_);
}
}
running_.clear();
finished_.clear();
constructed = false;
}
void Foam::JobInfo::jobEnding(const word& terminationType)
{
if (writeJobInfo && !finished_.empty())
{ {
add("cpuTime", cpuTime_.elapsedCpuTime()); add("cpuTime", cpuTime_.elapsedCpuTime());
add("endDate", clock::date()); add("endDate", clock::date());
add("endTime", clock::clockTime()); add("endTime", clock::clockTime());
if (!found("termination")) if (!terminationType.empty() && !found("termination"))
{ {
add("termination", terminationType); add("termination", terminationType);
} }
Foam::rm(runningDir_/jobFileName_); Foam::rm(running_);
write(OFstream(finishedDir_/jobFileName_)()); OFstream os(finished_);
if (!writeJobDict(os, *this))
{
std::cerr
<< "WARNING: could not write JobInfo file: "
<< finished_ << nl;
}
} }
running_.clear();
finished_.clear();
constructed = false; constructed = false;
} }
@ -94,14 +164,15 @@ void Foam::JobInfo::end(const word& terminationType)
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::JobInfo::JobInfo() Foam::JobInfo::JobInfo()
:
jobFileName_(),
runningDir_(),
finishedDir_(),
cpuTime_()
{ {
name() = "JobInfo"; if (constructed)
{
std::cerr
<< "WARNING: JobInfo was already constructed. "
"Should be a singleton!!" << nl;
}
// Only populate on master process, and when enabled
if (writeJobInfo && Pstream::master()) if (writeJobInfo && Pstream::master())
{ {
string jobDir = Foam::getEnv("FOAM_JOB_DIR"); string jobDir = Foam::getEnv("FOAM_JOB_DIR");
@ -109,31 +180,23 @@ Foam::JobInfo::JobInfo()
{ {
jobDir = home()/FOAM_RESOURCE_USER_CONFIG_DIRNAME/"jobControl"; jobDir = home()/FOAM_RESOURCE_USER_CONFIG_DIRNAME/"jobControl";
} }
string jobFile = hostName() + '.' + Foam::name(pid());
running_ = jobDir/"runningJobs"/jobFile;
finished_ = jobDir/"finishedJobs"/jobFile;
jobFileName_ = hostName() + '.' + Foam::name(pid()); if
runningDir_ = jobDir/"runningJobs"; (
finishedDir_ = jobDir/"finishedJobs"; !ensureJobDirExists(jobDir)
|| !ensureJobDirExists(running_.path())
if (!isDir(jobDir) && !mkDir(jobDir)) || !ensureJobDirExists(finished_.path())
)
{ {
FatalErrorInFunction running_.clear();
<< "No JobInfo directory: " << jobDir finished_.clear();
<< Foam::exit(FatalError);
}
if (!isDir(runningDir_) && !mkDir(runningDir_))
{
FatalErrorInFunction
<< "No JobInfo directory: " << runningDir_
<< Foam::exit(FatalError);
}
if (!isDir(finishedDir_) && !mkDir(finishedDir_))
{
FatalErrorInFunction
<< "No JobInfo directory: " << finishedDir_
<< Foam::exit(FatalError);
} }
} }
dictionary::name() = "JobInfo";
constructed = true; constructed = true;
} }
@ -142,7 +205,7 @@ Foam::JobInfo::JobInfo()
Foam::JobInfo::~JobInfo() Foam::JobInfo::~JobInfo()
{ {
signalEnd(); jobEnding();
} }
@ -150,45 +213,29 @@ Foam::JobInfo::~JobInfo()
void Foam::JobInfo::write() const void Foam::JobInfo::write() const
{ {
if (writeJobInfo && constructed && Pstream::master()) if (writeJobInfo && !running_.empty())
{ {
const fileName output = runningDir_/jobFileName_; OFstream os(running_);
if (!write(OFstream(output)())) if (!writeJobDict(os, *this))
{ {
FatalErrorInFunction std::cerr
<< "Failed to write to JobInfo file " << output << "WARNING: could not write JobInfo file: "
<< Foam::exit(FatalError); << running_ << nl;
// Normally does not happen
const_cast<fileName&>(running_).clear();
} }
} }
} }
void Foam::JobInfo::end() void Foam::JobInfo::stop() { jobEnding("normal"); }
{
end("normal");
}
void Foam::JobInfo::exit() { jobEnding("exit"); }
void Foam::JobInfo::exit() void Foam::JobInfo::abort() { jobEnding("abort"); }
{
end("exit");
}
void Foam::JobInfo::signalEnd() { jobEnding(); }
void Foam::JobInfo::abort()
{
end("abort");
}
void Foam::JobInfo::signalEnd() const
{
if (writeJobInfo && constructed && Pstream::master())
{
Foam::mv(runningDir_/jobFileName_, finishedDir_/jobFileName_);
}
constructed = false;
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2017 OpenCFD Ltd. Copyright (C) 2017-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -28,7 +28,8 @@ Class
Foam::JobInfo Foam::JobInfo
Description Description
Helper class for recording information about run/finished jobs. Helper class for recording information about run/finished jobs,
acts like global singleton.
Writes the following files: Writes the following files:
- $FOAM_JOB_DIR/runningJobs - $FOAM_JOB_DIR/runningJobs
@ -36,6 +37,11 @@ Description
If FOAM_JOB_DIR is unset, defaults to ~/.OpenFOAM/jobControl If FOAM_JOB_DIR is unset, defaults to ~/.OpenFOAM/jobControl
Note
JobInfo is treated as a largely failsafe operation.
If the directories cannot be written to,
only a warning (not an error) is emitted.
SourceFiles SourceFiles
JobInfo.C JobInfo.C
@ -45,7 +51,6 @@ SourceFiles
#define JobInfo_H #define JobInfo_H
#include "dictionary.H" #include "dictionary.H"
#include "fileName.H"
#include "cpuTime.H" #include "cpuTime.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -61,18 +66,34 @@ class JobInfo
: :
public dictionary public dictionary
{ {
// Private data // Private Data
//- The name of the job file //- Full path to "running" job information file (master only)
string jobFileName_; fileName running_;
fileName runningDir_;
fileName finishedDir_; //- Full path to "finished" job information file (master only)
fileName finished_;
//- Timing information
cpuTime cpuTime_; cpuTime cpuTime_;
// Private Member Functions // Private Member Functions
bool write(Ostream& os) const; //- Relocate job file from "running" to "finished" directory.
void end(const word& terminationType); // Invalidates job contents, clears 'constructed'.
void jobEnding();
//- Add elapsed times, termination type, remove file
//- from "running" and create in "finished" directory.
// Invalidates job contents, clears 'constructed'.
void jobEnding(const word& terminationType);
//- No copy construct
JobInfo(const JobInfo&) = delete;
//- No copy assignment
void operator=(const JobInfo&) = delete;
public: public:
@ -86,34 +107,55 @@ public:
// Constructors // Constructors
//- Construct null //- Default construct
JobInfo(); JobInfo();
//- Destructor //- Destructor, relocates the job file from running to finished.
// Update job info and relocate the file from running to finished.
~JobInfo(); ~JobInfo();
// Static Member Functions
//- Disallow JobInfo by forcing writeJobInfo (InfoSwitch) off.
static void disable() noexcept;
//- Simple shutdown (finalize) of JobInfo
// Relocates the job file from "running" to "finished".
// Invalidates job contents, clears 'constructed'.
static void shutdown();
//- Exit or abort shutdown (finalize) of JobInfo
static void shutdown(bool isAbort);
// Member Functions // Member Functions
//- Write the job info to its file in the runningJobs directory //- Write job info to its file in the "running" jobs directory
void write() const; void write() const;
//- End with "termination=normal" //- Job end with "normal" termination
void end(); void stop();
//- End with "termination=exit" //- Job end with "exit" termination
void exit(); void exit();
//- End with "termination=abort" //- Job end with "abort" termination
void abort(); void abort();
//- Update job info and relocate the file from running to finished. //- Relocate job file from "running" to "finished" directory.
void signalEnd() const; // Invalidates job contents, clears 'constructed'.
void signalEnd();
// Housekeeping
//- Same as stop
void end() { stop(); }
}; };
// Job information bookkeeping (global)
extern JobInfo jobInfo; extern JobInfo jobInfo;

View File

@ -486,7 +486,7 @@ void Foam::argList::noFunctionObjects(bool addWithOption)
void Foam::argList::noJobInfo() void Foam::argList::noJobInfo()
{ {
JobInfo::writeJobInfo = false; JobInfo::disable();
} }
@ -1063,12 +1063,9 @@ void Foam::argList::parse
jobInfo.add("startDate", dateString); jobInfo.add("startDate", dateString);
jobInfo.add("startTime", timeString); jobInfo.add("startTime", timeString);
jobInfo.add("userName", userName()); jobInfo.add("userName", userName());
jobInfo.add("foamApi", foamVersion::api);
jobInfo.add("foamVersion", word(foamVersion::version)); jobInfo.add("foamVersion", word(foamVersion::version));
jobInfo.add("code", executable_);
jobInfo.add("argList", commandLine_);
jobInfo.add("currentDir", cwd());
jobInfo.add("PPID", ppid());
jobInfo.add("PGID", pgid());
// Add build information - only use the first word // Add build information - only use the first word
{ {
@ -1081,6 +1078,12 @@ void Foam::argList::parse
jobInfo.add("foamBuild", build); jobInfo.add("foamBuild", build);
} }
jobInfo.add("code", executable_);
jobInfo.add("argList", commandLine_);
jobInfo.add("currentDir", cwd());
jobInfo.add("PPID", ppid());
jobInfo.add("PGID", pgid());
// Load additional libraries (verbosity according to banner setting) // Load additional libraries (verbosity according to banner setting)
libs().open(bannerEnabled()); libs().open(bannerEnabled());
} }
@ -1635,7 +1638,7 @@ void Foam::argList::parse
Foam::argList::~argList() Foam::argList::~argList()
{ {
jobInfo.end(); jobInfo.stop(); // Normal job termination
// Delete file handler to flush any remaining IO // Delete file handler to flush any remaining IO
Foam::fileHandler(nullptr); Foam::fileHandler(nullptr);