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 |
-------------------------------------------------------------------------------
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;
if (useIOerr)
{
FatalIOErrorInFunction(dict)
<< "This is an error from 1" << nl
<< "Explanation to follow:" << endl;
FatalErrorInFunction
<< "Error 2"
<< exit(FatalError);
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;

View File

@ -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)

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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_)
{

View File

@ -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)

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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_)
{

View File

@ -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

View File

@ -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_)
{
if (!isAbort)
{
// Make a copy of the error to throw
IOerror errorException(*this);
// Reset the message buffer for the next error message
messageStreamPtr_->reset();
throw errorException;
return;
}
}
else if (JobInfo::constructed)
{
jobInfo.add("FatalIOError", operator dictionary());
if (isAbort || error::useAbort())
{
jobInfo.abort();
}
else
{
jobInfo.exit();
}
JobInfo::shutdown(isAbort || error::useAbort());
}
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();
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);
}
}
else
{
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);
}
}
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;
}

View File

@ -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_)
{
if (!isAbort)
{
// 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;
}
}
else if (JobInfo::constructed)
{
jobInfo.add("FatalError", operator dictionary());
if (isAbort || error::useAbort())
{
jobInfo.abort();
}
else
{
jobInfo.exit();
}
JobInfo::shutdown(isAbort || error::useAbort());
}
if (throwing_ && !isAbort)
{
// Make a copy of the error to throw
error errorException(*this);
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;
}

View File

@ -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;

View File

@ -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

View File

@ -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
// * * * * * * * * * * * * * 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))
{
if (os.good())
{
dictionary::write(os, false);
return true;
}
else
{
return false;
}
std::cerr
<< "WARNING: no JobInfo directory: " << dir << nl
<< " disabling JobInfo" << nl;
return false;
}
return true;
}
void Foam::JobInfo::end(const word& terminationType)
// Write dictionary entries (called on master only)
static inline bool writeJobDict(Ostream& os, const dictionary& dict)
{
if (writeJobInfo && constructed && Pstream::master())
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 * * * * * * * * * * * //
void Foam::JobInfo::jobEnding()
{
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("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";
}
string jobFile = hostName() + '.' + Foam::name(pid());
running_ = jobDir/"runningJobs"/jobFile;
finished_ = jobDir/"finishedJobs"/jobFile;
jobFileName_ = hostName() + '.' + Foam::name(pid());
runningDir_ = jobDir/"runningJobs";
finishedDir_ = jobDir/"finishedJobs";
if (!isDir(jobDir) && !mkDir(jobDir))
if
(
!ensureJobDirExists(jobDir)
|| !ensureJobDirExists(running_.path())
|| !ensureJobDirExists(finished_.path())
)
{
FatalErrorInFunction
<< "No JobInfo directory: " << jobDir
<< 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);
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(); }
// ************************************************************************* //

View File

@ -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;

View File

@ -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);