From cc5aa2093127e9676e5ae67e22b6424460d34979 Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Thu, 1 Jul 2021 14:16:46 +0200 Subject: [PATCH] ENH: simplify exit/abort handling and jobinfo (code reduction) - handle failures more robustly - add static shutdown() for similarity with Pstream etc. --- applications/test/error/Test-error.C | 54 +++-- src/OSspecific/MSwindows/signals/sigFpe.C | 4 +- src/OSspecific/MSwindows/signals/sigInt.C | 4 +- src/OSspecific/MSwindows/signals/sigQuit.C | 4 +- src/OSspecific/MSwindows/signals/sigSegv.C | 4 +- .../MSwindows/signals/sigStopAtWriteNow.C | 4 +- src/OSspecific/POSIX/signals/sigFpe.C | 4 +- src/OSspecific/POSIX/signals/sigInt.C | 4 +- src/OSspecific/POSIX/signals/sigQuit.C | 4 +- src/OSspecific/POSIX/signals/sigSegv.C | 4 +- .../POSIX/signals/sigStopAtWriteNow.C | 4 +- src/OpenFOAM/Make/files | 1 + src/OpenFOAM/db/error/IOerror.C | 85 ++------ src/OpenFOAM/db/error/error.C | 46 +++-- src/OpenFOAM/db/error/error.H | 68 +++--- src/OpenFOAM/db/error/messageStream.H | 16 +- src/OpenFOAM/global/JobInfo/JobInfo.C | 195 +++++++++++------- src/OpenFOAM/global/JobInfo/JobInfo.H | 84 ++++++-- src/OpenFOAM/global/argList/argList.C | 17 +- 19 files changed, 344 insertions(+), 262 deletions(-) diff --git a/applications/test/error/Test-error.C b/applications/test/error/Test-error.C index 550726330ba..3e25fe9da0b 100644 --- a/applications/test/error/Test-error.C +++ b/applications/test/error/Test-error.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2015 OpenFOAM Foundation - Copyright (C) 2020 OpenCFD Ltd. + Copyright (C) 2020-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -37,10 +37,13 @@ using namespace Foam; 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 args(argc, argv); + #if 0 if (true) { InfoErr<< "Called with " << (args.size()-1) << " args\n"; @@ -49,7 +52,13 @@ int main(int argc, char *argv[]) } #endif - FatalError.throwExceptions(); + const bool useIOerr = args.found("ioerror"); + + if (!args.found("no-throw")) + { + FatalIOError.throwExceptions(); + FatalError.throwExceptions(); + } try { @@ -60,17 +69,34 @@ int main(int argc, char *argv[]) IOWarningInFunction(dict) << "warning 3" << endl; - FatalErrorInFunction - << "This is an error from 1" << nl - << "Explanation to follow:" << endl; - - FatalErrorInFunction - << "Error 2" - << exit(FatalError); + if (useIOerr) + { + FatalIOErrorInFunction(dict) + << "This is an error from 1" << nl + << "Explanation to follow:" << endl; + + FatalIOError + << "Error 2" + << exit(FatalIOError); + } + else + { + FatalErrorInFunction + << "This is an error from 1" << nl + << "Explanation to follow:" << endl; + + FatalError + << "Error 2" + << exit(FatalError); + } + } + catch (const Foam::IOerror& err) + { + Serr<< "Caught IO error " << err << nl << endl; } catch (const Foam::error& err) { - Serr<< "Caught Foam error " << err << nl << endl; + Serr<< "Caught error " << err << nl << endl; } try @@ -79,9 +105,13 @@ int main(int argc, char *argv[]) << "Error# 3" << exit(FatalError); } + catch (const Foam::IOerror& err) + { + Serr<< "Caught IO error " << err << nl << endl; + } catch (const Foam::error& err) { - Serr<< "Caught Foam error " << err << nl << endl; + Serr<< "Caught error " << err << nl << endl; } return 0; diff --git a/src/OSspecific/MSwindows/signals/sigFpe.C b/src/OSspecific/MSwindows/signals/sigFpe.C index a00e7929df6..0a06c4c30ad 100644 --- a/src/OSspecific/MSwindows/signals/sigFpe.C +++ b/src/OSspecific/MSwindows/signals/sigFpe.C @@ -7,7 +7,7 @@ ------------------------------------------------------------------------------- Copyright (C) 2011-2015 OpenFOAM Foundation Copyright (C) 2011 Symscape - Copyright (C) 2016-2020 OpenCFD Ltd. + Copyright (C) 2016-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -87,7 +87,7 @@ void Foam::sigFpe::sigHandler(int) { resetHandler("SIGFPE", SIGFPE); - jobInfo.signalEnd(); // Update jobInfo file + JobInfo::shutdown(); // From running -> finished error::printStack(Perr); clearFpe(); ::raise(SIGFPE); // Throw signal (to old handler) diff --git a/src/OSspecific/MSwindows/signals/sigInt.C b/src/OSspecific/MSwindows/signals/sigInt.C index 2c8db81f28b..c4114968ba3 100644 --- a/src/OSspecific/MSwindows/signals/sigInt.C +++ b/src/OSspecific/MSwindows/signals/sigInt.C @@ -7,7 +7,7 @@ ------------------------------------------------------------------------------- Copyright (C) 2011-2015 OpenFOAM Foundation Copyright (C) 2011 Symscape - Copyright (C) 2018-2019 OpenCFD Ltd. + Copyright (C) 2018-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -47,7 +47,7 @@ void Foam::sigInt::sigHandler(int) { resetHandler("SIGINT", SIGINT); - jobInfo.signalEnd(); // Update jobInfo file + JobInfo::shutdown(); // From running -> finished ::raise(SIGINT); // Throw signal (to old handler) } diff --git a/src/OSspecific/MSwindows/signals/sigQuit.C b/src/OSspecific/MSwindows/signals/sigQuit.C index 40de3250186..cb33f036ae0 100644 --- a/src/OSspecific/MSwindows/signals/sigQuit.C +++ b/src/OSspecific/MSwindows/signals/sigQuit.C @@ -7,7 +7,7 @@ ------------------------------------------------------------------------------- Copyright (C) 2011-2015 OpenFOAM Foundation Copyright (C) 2011 Symscape - Copyright (C) 2018-2019 OpenCFD Ltd. + Copyright (C) 2018-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -49,7 +49,7 @@ void Foam::sigQuit::sigHandler(int) { resetHandler("SIGBREAK", SIGBREAK); - jobInfo.signalEnd(); // Update jobInfo file + JobInfo::shutdown(); // From running -> finished error::printStack(Perr); ::raise(SIGBREAK); // Throw signal (to old handler) } diff --git a/src/OSspecific/MSwindows/signals/sigSegv.C b/src/OSspecific/MSwindows/signals/sigSegv.C index ac802524706..9fe56674f49 100644 --- a/src/OSspecific/MSwindows/signals/sigSegv.C +++ b/src/OSspecific/MSwindows/signals/sigSegv.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2015 OpenFOAM Foundation - Copyright (C) 2018-2019 OpenCFD Ltd. + Copyright (C) 2018-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -46,7 +46,7 @@ void Foam::sigSegv::sigHandler(int) { resetHandler("SIGSEGV", SIGSEGV); - jobInfo.signalEnd(); // Update jobInfo file + JobInfo::shutdown(); // From running -> finished error::printStack(Perr); ::raise(SIGSEGV); // Throw signal (to old handler) } diff --git a/src/OSspecific/MSwindows/signals/sigStopAtWriteNow.C b/src/OSspecific/MSwindows/signals/sigStopAtWriteNow.C index 0923e110d49..25a7234923a 100644 --- a/src/OSspecific/MSwindows/signals/sigStopAtWriteNow.C +++ b/src/OSspecific/MSwindows/signals/sigStopAtWriteNow.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2016-2019 OpenCFD Ltd. + Copyright (C) 2016-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -95,7 +95,7 @@ void Foam::sigStopAtWriteNow::sigHandler(int) { resetHandler("stopAtWriteNow", signal_); - jobInfo.signalEnd(); // Update jobInfo file + JobInfo::shutdown(); // From running -> finished if (runTimePtr_) { diff --git a/src/OSspecific/POSIX/signals/sigFpe.C b/src/OSspecific/POSIX/signals/sigFpe.C index 29a95852597..110fff0131c 100644 --- a/src/OSspecific/POSIX/signals/sigFpe.C +++ b/src/OSspecific/POSIX/signals/sigFpe.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2015 OpenFOAM Foundation - Copyright (C) 2016-2020 OpenCFD Ltd. + Copyright (C) 2016-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -121,7 +121,7 @@ void Foam::sigFpe::sigHandler(int) resetHandler("SIGFPE", SIGFPE); - jobInfo.signalEnd(); // Update jobInfo file + JobInfo::shutdown(); // From running -> finished error::printStack(Perr); ::raise(SIGFPE); // Throw signal (to old handler) diff --git a/src/OSspecific/POSIX/signals/sigInt.C b/src/OSspecific/POSIX/signals/sigInt.C index 699d0329778..f50b20dca83 100644 --- a/src/OSspecific/POSIX/signals/sigInt.C +++ b/src/OSspecific/POSIX/signals/sigInt.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2015 OpenFOAM Foundation - Copyright (C) 2018-2019 OpenCFD Ltd. + Copyright (C) 2018-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -46,7 +46,7 @@ void Foam::sigInt::sigHandler(int) { resetHandler("SIGINT", SIGINT); - jobInfo.signalEnd(); // Update jobInfo file + JobInfo::shutdown(); // From running -> finished ::raise(SIGINT); // Throw signal (to old handler) } diff --git a/src/OSspecific/POSIX/signals/sigQuit.C b/src/OSspecific/POSIX/signals/sigQuit.C index ea61d8db5a6..dda6ff025bd 100644 --- a/src/OSspecific/POSIX/signals/sigQuit.C +++ b/src/OSspecific/POSIX/signals/sigQuit.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2015 OpenFOAM Foundation - Copyright (C) 2017-2019 OpenCFD Ltd. + Copyright (C) 2017-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -46,7 +46,7 @@ void Foam::sigQuit::sigHandler(int) { resetHandler("SIGQUIT", SIGQUIT); - jobInfo.signalEnd(); // Update jobInfo file + JobInfo::shutdown(); // From running -> finished error::printStack(Perr); ::raise(SIGQUIT); // Throw signal (to old handler) } diff --git a/src/OSspecific/POSIX/signals/sigSegv.C b/src/OSspecific/POSIX/signals/sigSegv.C index ac802524706..9fe56674f49 100644 --- a/src/OSspecific/POSIX/signals/sigSegv.C +++ b/src/OSspecific/POSIX/signals/sigSegv.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2015 OpenFOAM Foundation - Copyright (C) 2018-2019 OpenCFD Ltd. + Copyright (C) 2018-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -46,7 +46,7 @@ void Foam::sigSegv::sigHandler(int) { resetHandler("SIGSEGV", SIGSEGV); - jobInfo.signalEnd(); // Update jobInfo file + JobInfo::shutdown(); // From running -> finished error::printStack(Perr); ::raise(SIGSEGV); // Throw signal (to old handler) } diff --git a/src/OSspecific/POSIX/signals/sigStopAtWriteNow.C b/src/OSspecific/POSIX/signals/sigStopAtWriteNow.C index 4ca10d49dc6..f6644c34319 100644 --- a/src/OSspecific/POSIX/signals/sigStopAtWriteNow.C +++ b/src/OSspecific/POSIX/signals/sigStopAtWriteNow.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2016-2019 OpenCFD Ltd. + Copyright (C) 2016-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -97,7 +97,7 @@ void Foam::sigStopAtWriteNow::sigHandler(int) { resetHandler("stopAtWriteNow", signal_); - jobInfo.signalEnd(); // Update jobInfo file + JobInfo::shutdown(); // From running -> finished if (runTimePtr_) { diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files index cd25b075df9..5f519001307 100644 --- a/src/OpenFOAM/Make/files +++ b/src/OpenFOAM/Make/files @@ -2,6 +2,7 @@ global/foamConfig.Cver global/globals.C /* global/constants/constants.C in globals.C */ /* global/constants/dimensionedConstants.C in globals.C */ +/* global/JobInfo/JobInfo.C in globals.C */ global/argList/argList.C global/argList/argListHelp.C global/clock/clock.C diff --git a/src/OpenFOAM/db/error/IOerror.C b/src/OpenFOAM/db/error/IOerror.C index 588aea16390..93acd448e38 100644 --- a/src/OpenFOAM/db/error/IOerror.C +++ b/src/OpenFOAM/db/error/IOerror.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2015-2020 OpenCFD Ltd. + Copyright (C) 2015-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -159,9 +159,7 @@ Foam::IOerror::operator Foam::dictionary() const { dictionary errDict(error::operator dictionary()); - errDict.remove("type"); - errDict.add("type", word("Foam::IOerror")); - + errDict.add("type", word("Foam::IOerror"), true); // overwrite errDict.add("ioFileName", ioFileName()); errDict.add("ioStartLineNumber", ioStartLineNumber()); errDict.add("ioEndLineNumber", ioEndLineNumber()); @@ -172,75 +170,29 @@ Foam::IOerror::operator Foam::dictionary() const // * * * * * * * * * * * * * 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 || error::useAbort()) - { - jobInfo.abort(); - } - else + if (!isAbort) { - jobInfo.exit(); - } - } + // Make a copy of the error to throw + IOerror errorException(*this); - if (throwing_ && !isAbort) - { - // Make a copy of the error to throw - IOerror errorException(*this); - - // Reset the message buffer for the next error message - messageStreamPtr_->reset(); + // Reset the message buffer for the next error message + messageStreamPtr_->reset(); - throw errorException; - } - 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); + throw errorException; + return; } } - else + else if (JobInfo::constructed) { - if (isAbort) - { - Perr<< nl << *this << nl - << "\nFOAM aborting\n" << endl; - error::printStack(Perr); - - #ifdef _WIN32 - 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); - } + jobInfo.add("FatalIOError", operator dictionary()); + JobInfo::shutdown(isAbort || error::useAbort()); } + + simpleExit(errNo, isAbort); } @@ -248,13 +200,13 @@ void Foam::IOerror::exitOrAbort(const int errNo, const bool isAbort) void Foam::IOerror::exit(const int) { - exitOrAbort(1, false); + exiting(1, false); } 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) { err.write(os); - return os; } diff --git a/src/OpenFOAM/db/error/error.C b/src/OpenFOAM/db/error/error.C index 270db524cf3..46ada0c4681 100644 --- a/src/OpenFOAM/db/error/error.C +++ b/src/OpenFOAM/db/error/error.C @@ -199,32 +199,37 @@ Foam::error::operator Foam::dictionary() const // * * * * * * * * * * * * * 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 || error::useAbort()) - { - jobInfo.abort(); - } - else + if (!isAbort) { - jobInfo.exit(); + // Make a copy of the error to throw + error errorException(*this); + + // Reset the message buffer for the next error message + messageStreamPtr_->reset(); + + throw errorException; + return; } } - - if (throwing_ && !isAbort) + else if (JobInfo::constructed) { - // Make a copy of the error to throw - error errorException(*this); + jobInfo.add("FatalError", operator dictionary()); + JobInfo::shutdown(isAbort || error::useAbort()); + } + + simpleExit(errNo, isAbort); +} - // Reset the message buffer for the next error message - messageStreamPtr_->reset(); - throw errorException; - } - else if (error::useAbort()) +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +void Foam::error::simpleExit(const int errNo, const bool isAbort) +{ + if (error::useAbort()) { Perr<< nl << *this << nl << "\nFOAM aborting (FOAM_ABORT set)\n" << endl; @@ -287,13 +292,13 @@ void Foam::error::clear() const void Foam::error::exit(const int errNo) { - exitOrAbort(errNo, false); + exiting(errNo, false); } 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) { err.write(os); - return os; } diff --git a/src/OpenFOAM/db/error/error.H b/src/OpenFOAM/db/error/error.H index 3ce8c20db2d..62cc4d48fad 100644 --- a/src/OpenFOAM/db/error/error.H +++ b/src/OpenFOAM/db/error/error.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2015 OpenFOAM Foundation - Copyright (C) 2015-2020 OpenCFD Ltd. + Copyright (C) 2015-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -75,8 +75,8 @@ class error { // Private Member Functions - //- Common code for exit or abort - void exitOrAbort(const int errNo, const bool isAbort); + //- Exit or abort code, with exception and jobinfo handling + void exiting(const int errNo, const bool isAbort); protected: @@ -90,6 +90,12 @@ protected: 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: // Constructors @@ -126,48 +132,34 @@ public: //- Clear any messages void clear() const; - const string& functionName() const + const string& functionName() const noexcept { return functionName_; } - const string& sourceFileName() const + const string& sourceFileName() const noexcept { return sourceFileName_; } - label sourceFileLineNumber() const + label sourceFileLineNumber() const noexcept { return sourceFileLineNumber_; } - //- Return the current exception throwing (on or off) - bool throwing() const + //- Return the current exception throwing state (on or off) + bool throwing() const noexcept { return throwing_; } - //- Activate/deactivate exception throwing + //- Specify exception throwing (default is activate) // \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; - return prev; - } - - //- 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); + return old; } //- Define basic print message @@ -204,7 +196,7 @@ public: //- Convert to OSstream operator OSstream&(); - //- Create and return a dictionary representation of the error + //- Return a dictionary representation of the error operator dictionary() const; @@ -228,6 +220,16 @@ public: //- Print error message 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 - //- Common code for exit or abort - void exitOrAbort(const int errNo, const bool isAbort); + //- Exit or abort code, with exception and jobinfo handling + void exiting(const int errNo, const bool isAbort); public: @@ -270,17 +272,17 @@ public: // Member Functions - const string& ioFileName() const + const string& ioFileName() const noexcept { return ioFileName_; } - label ioStartLineNumber() const + label ioStartLineNumber() const noexcept { return ioStartLineNumber_; } - label ioEndLineNumber() const + label ioEndLineNumber() const noexcept { return ioEndLineNumber_; } @@ -329,7 +331,7 @@ public: const string& msg ); - //- Create and return a dictionary representation of the error + //- Return a dictionary representation of the error operator dictionary() const; diff --git a/src/OpenFOAM/db/error/messageStream.H b/src/OpenFOAM/db/error/messageStream.H index 1ab03aa95be..81ba4252a06 100644 --- a/src/OpenFOAM/db/error/messageStream.H +++ b/src/OpenFOAM/db/error/messageStream.H @@ -127,25 +127,27 @@ public: explicit messageStream(const dictionary& dict); - // Member functions + // Member Functions //- The title of this error type - const string& title() const + const string& title() const noexcept { return title_; } //- The maximum number of errors before program termination - int maxErrors() const + int maxErrors() const noexcept { return maxErrors_; } - //- Non-const access to the maximum number of errors before - //- program termination to enable user to reset it - int& maxErrors() + //- Set the maximum number of errors before program termination + // \return the previous value for maxErrors + int maxErrors(int nErrors) noexcept { - return maxErrors_; + int old = maxErrors_; + maxErrors_ = nErrors; + return old; } //- Convert to OSstream diff --git a/src/OpenFOAM/global/JobInfo/JobInfo.C b/src/OpenFOAM/global/JobInfo/JobInfo.C index aedfe250cf6..d014befbaea 100644 --- a/src/OpenFOAM/global/JobInfo/JobInfo.C +++ b/src/OpenFOAM/global/JobInfo/JobInfo.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2017-2018 OpenCFD Ltd. + Copyright (C) 2017-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -27,9 +27,9 @@ License \*---------------------------------------------------------------------------*/ #include "JobInfo.H" -#include "OSspecific.H" #include "clock.H" #include "OFstream.H" +#include "OSspecific.H" #include "Pstream.H" #include "foamVersion.H" @@ -48,45 +48,115 @@ License bool Foam::JobInfo::writeJobInfo(Foam::debug::infoSwitch("writeJobInfo", 0)); Foam::JobInfo Foam::jobInfo; +// Foam::JobInfo::constructed defined in globals.C + + +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +namespace Foam +{ + +// 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()) + { + dict.writeEntries(os, true); // With extraNewLine=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 + { + jobInfo.jobEnding("exit"); + } +} + // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // -bool Foam::JobInfo::write(Ostream& os) const +void Foam::JobInfo::jobEnding() { - if (writeJobInfo && Pstream::master()) + if (!running_.empty()) { - if (os.good()) - { - dictionary::write(os, false); - return true; - } - else + if (!Foam::mv(running_, finished_)) { - return false; + Foam::rm(running_); } } - return true; + running_.clear(); + finished_.clear(); + constructed = false; } -void Foam::JobInfo::end(const word& terminationType) +void Foam::JobInfo::jobEnding(const word& terminationType) { - if (writeJobInfo && constructed && Pstream::master()) + if (writeJobInfo && !finished_.empty()) { add("cpuTime", cpuTime_.elapsedCpuTime()); add("endDate", clock::date()); add("endTime", clock::clockTime()); - if (!found("termination")) + if (!terminationType.empty() && !found("termination")) { add("termination", terminationType); } - Foam::rm(runningDir_/jobFileName_); - write(OFstream(finishedDir_/jobFileName_)()); + Foam::rm(running_); + OFstream os(finished_); + if (!writeJobDict(os, *this)) + { + std::cerr + << "WARNING: could not write JobInfo file: " + << finished_ << nl; + } } + running_.clear(); + finished_.clear(); constructed = false; } @@ -94,14 +164,15 @@ void Foam::JobInfo::end(const word& terminationType) // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // 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()) { string jobDir = Foam::getEnv("FOAM_JOB_DIR"); @@ -109,31 +180,23 @@ Foam::JobInfo::JobInfo() { jobDir = home()/FOAM_RESOURCE_USER_CONFIG_DIRNAME/"jobControl"; } - - jobFileName_ = hostName() + '.' + Foam::name(pid()); - runningDir_ = jobDir/"runningJobs"; - finishedDir_ = jobDir/"finishedJobs"; - - if (!isDir(jobDir) && !mkDir(jobDir)) - { - FatalErrorInFunction - << "No JobInfo directory: " << jobDir - << Foam::exit(FatalError); - } - if (!isDir(runningDir_) && !mkDir(runningDir_)) + string jobFile = hostName() + '.' + Foam::name(pid()); + running_ = jobDir/"runningJobs"/jobFile; + finished_ = jobDir/"finishedJobs"/jobFile; + + if + ( + !ensureJobDirExists(jobDir) + || !ensureJobDirExists(running_.path()) + || !ensureJobDirExists(finished_.path()) + ) { - FatalErrorInFunction - << "No JobInfo directory: " << runningDir_ - << Foam::exit(FatalError); - } - if (!isDir(finishedDir_) && !mkDir(finishedDir_)) - { - FatalErrorInFunction - << "No JobInfo directory: " << finishedDir_ - << Foam::exit(FatalError); + running_.clear(); + finished_.clear(); } } + dictionary::name() = "JobInfo"; constructed = true; } @@ -142,7 +205,7 @@ Foam::JobInfo::JobInfo() Foam::JobInfo::~JobInfo() { - signalEnd(); + jobEnding(); } @@ -150,45 +213,29 @@ Foam::JobInfo::~JobInfo() void Foam::JobInfo::write() const { - if (writeJobInfo && constructed && Pstream::master()) + if (writeJobInfo && !running_.empty()) { - const fileName output = runningDir_/jobFileName_; - if (!write(OFstream(output)())) + OFstream os(running_); + if (!writeJobDict(os, *this)) { - FatalErrorInFunction - << "Failed to write to JobInfo file " << output - << Foam::exit(FatalError); + std::cerr + << "WARNING: could not write JobInfo file: " + << running_ << nl; + + // Normally does not happen + const_cast<fileName&>(running_).clear(); } } } -void Foam::JobInfo::end() -{ - end("normal"); -} +void Foam::JobInfo::stop() { jobEnding("normal"); } +void Foam::JobInfo::exit() { jobEnding("exit"); } -void Foam::JobInfo::exit() -{ - end("exit"); -} +void Foam::JobInfo::abort() { jobEnding("abort"); } - -void Foam::JobInfo::abort() -{ - end("abort"); -} - - -void Foam::JobInfo::signalEnd() const -{ - if (writeJobInfo && constructed && Pstream::master()) - { - Foam::mv(runningDir_/jobFileName_, finishedDir_/jobFileName_); - } - constructed = false; -} +void Foam::JobInfo::signalEnd() { jobEnding(); } // ************************************************************************* // diff --git a/src/OpenFOAM/global/JobInfo/JobInfo.H b/src/OpenFOAM/global/JobInfo/JobInfo.H index d330b0e78df..1cf6a9917d1 100644 --- a/src/OpenFOAM/global/JobInfo/JobInfo.H +++ b/src/OpenFOAM/global/JobInfo/JobInfo.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011 OpenFOAM Foundation - Copyright (C) 2017 OpenCFD Ltd. + Copyright (C) 2017-2021 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -28,7 +28,8 @@ Class Foam::JobInfo 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: - $FOAM_JOB_DIR/runningJobs @@ -36,6 +37,11 @@ Description 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 JobInfo.C @@ -45,7 +51,6 @@ SourceFiles #define JobInfo_H #include "dictionary.H" -#include "fileName.H" #include "cpuTime.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -61,18 +66,34 @@ class JobInfo : public dictionary { - // Private data + // Private Data + + //- Full path to "running" job information file (master only) + fileName running_; + + //- Full path to "finished" job information file (master only) + fileName finished_; + + //- Timing information + cpuTime cpuTime_; - //- The name of the job file - string jobFileName_; - fileName runningDir_; - fileName finishedDir_; - cpuTime cpuTime_; // Private Member Functions - bool write(Ostream& os) const; - void end(const word& terminationType); + //- Relocate job file from "running" to "finished" directory. + // 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: @@ -86,34 +107,55 @@ public: // Constructors - //- Construct null + //- Default construct JobInfo(); - //- Destructor - // Update job info and relocate the file from running to finished. + //- Destructor, relocates the job file from running to finished. ~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 - //- 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; - //- End with "termination=normal" - void end(); + //- Job end with "normal" termination + void stop(); - //- End with "termination=exit" + //- Job end with "exit" termination void exit(); - //- End with "termination=abort" + //- Job end with "abort" termination void abort(); - //- Update job info and relocate the file from running to finished. - void signalEnd() const; + //- Relocate job file from "running" to "finished" directory. + // Invalidates job contents, clears 'constructed'. + void signalEnd(); + + + // Housekeeping + + //- Same as stop + void end() { stop(); } }; +// Job information bookkeeping (global) extern JobInfo jobInfo; diff --git a/src/OpenFOAM/global/argList/argList.C b/src/OpenFOAM/global/argList/argList.C index f4b26f38f84..9eb2fb42935 100644 --- a/src/OpenFOAM/global/argList/argList.C +++ b/src/OpenFOAM/global/argList/argList.C @@ -486,7 +486,7 @@ void Foam::argList::noFunctionObjects(bool addWithOption) void Foam::argList::noJobInfo() { - JobInfo::writeJobInfo = false; + JobInfo::disable(); } @@ -1063,12 +1063,9 @@ void Foam::argList::parse jobInfo.add("startDate", dateString); jobInfo.add("startTime", timeString); jobInfo.add("userName", userName()); + + jobInfo.add("foamApi", foamVersion::api); 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 { @@ -1081,6 +1078,12 @@ void Foam::argList::parse 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) libs().open(bannerEnabled()); } @@ -1635,7 +1638,7 @@ void Foam::argList::parse Foam::argList::~argList() { - jobInfo.end(); + jobInfo.stop(); // Normal job termination // Delete file handler to flush any remaining IO Foam::fileHandler(nullptr); -- GitLab