Merge pull request #14082 from Ondsel-Development/issue_13522_fix_read_lock

Core: Add read lock to fix for possible race conditions reading/writing config files
This commit is contained in:
Chris Hennes
2024-05-27 10:41:23 -05:00
committed by GitHub
5 changed files with 67 additions and 13 deletions

View File

@@ -1674,19 +1674,29 @@ void Application::cleanupUnits()
void Application::destruct()
{
// saving system parameter
Base::Console().Log("Saving system parameter...\n");
_pcSysParamMngr->SaveDocument();
if (_pcSysParamMngr->IgnoreSave()) {
Base::Console().Warning("Discard system parameter\n");
}
else {
Base::Console().Log("Saving system parameter...\n");
_pcSysParamMngr->SaveDocument();
Base::Console().Log("Saving system parameter...done\n");
}
// saving the User parameter
Base::Console().Log("Saving system parameter...done\n");
Base::Console().Log("Saving user parameter...\n");
_pcUserParamMngr->SaveDocument();
Base::Console().Log("Saving user parameter...done\n");
if (_pcUserParamMngr->IgnoreSave()) {
Base::Console().Warning("Discard user parameter\n");
}
else {
Base::Console().Log("Saving user parameter...\n");
_pcUserParamMngr->SaveDocument();
Base::Console().Log("Saving user parameter...done\n");
}
// now save all other parameter files
auto& paramMgr = _pcSingleton->mpcPramManager;
for (auto it : paramMgr) {
if ((it.second != _pcSysParamMngr) && (it.second != _pcUserParamMngr)) {
if (it.second->HasSerializer()) {
if (it.second->HasSerializer() && !it.second->IgnoreSave()) {
Base::Console().Log("Saving %s...\n", it.first.c_str());
it.second->SaveDocument();
Base::Console().Log("Saving %s...done\n", it.first.c_str());

View File

@@ -1617,6 +1617,7 @@ ParameterManager::ParameterManager()
// ---------------------------------------------------------------------------
// NOLINTBEGIN
gIgnoreSave = false;
gDoNamespaces = false;
gDoSchema = false;
gSchemaFullChecking = false;
@@ -1723,14 +1724,28 @@ void ParameterManager::SaveDocument() const
}
}
void ParameterManager::SetIgnoreSave(bool value)
{
gIgnoreSave = value;
}
bool ParameterManager::IgnoreSave() const
{
return gIgnoreSave;
}
namespace
{
void waitForFileAccess(const Base::FileInfo& file)
QString getLockFile(const Base::FileInfo& file)
{
QFileInfo fi(QDir::tempPath(), QString::fromStdString(file.fileName() + ".lock"));
QLockFile lock(fi.absoluteFilePath());
const int waitOneSecond = 1000;
lock.tryLock(waitOneSecond);
return fi.absoluteFilePath();
}
int getTimeout()
{
const int timeout = 5000;
return timeout;
}
} // namespace
@@ -1753,7 +1768,14 @@ int ParameterManager::LoadDocument(const char* sFileName)
{
try {
Base::FileInfo file(sFileName);
waitForFileAccess(file);
QLockFile lock(getLockFile(file));
if (!lock.tryLock(getTimeout())) {
// Continue with empty config
CreateDocument();
SetIgnoreSave(true);
std::cerr << "Failed to access file for reading: " << sFileName << std::endl;
return 1;
}
#if defined(FC_OS_WIN32)
std::wstring name = file.toStdWString();
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
@@ -1845,7 +1867,11 @@ void ParameterManager::SaveDocument(const char* sFileName) const
{
try {
Base::FileInfo file(sFileName);
waitForFileAccess(file);
QLockFile lock(getLockFile(file));
if (!lock.tryLock(getTimeout())) {
std::cerr << "Failed to access file for writing: " << sFileName << std::endl;
return;
}
//
// Plug in a format target to receive the resultant
// XML stream from the serializer.

View File

@@ -434,12 +434,15 @@ public:
bool LoadOrCreateDocument();
/// Saves an XML document by calling the serializer's save method.
void SaveDocument() const;
void SetIgnoreSave(bool value);
bool IgnoreSave() const;
//@}
private:
XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* _pDocument {nullptr};
ParameterSerializer* paramSerializer {nullptr};
bool gIgnoreSave;
bool gDoNamespaces;
bool gDoSchema;
bool gSchemaFullChecking;

View File

@@ -43,6 +43,7 @@
#include "MainWindow.h"
#include "Language/Translator.h"
#include <App/Application.h>
#include <Base/Console.h>
using namespace Gui;
@@ -233,6 +234,7 @@ void StartupPostProcess::execute()
setBranding();
showMainWindow();
activateWorkbench();
checkParameters();
}
void StartupPostProcess::setWindowTitle()
@@ -545,3 +547,15 @@ void StartupPostProcess::autoloadModules(const QStringList& wb)
}
}
}
void StartupPostProcess::checkParameters()
{
if (App::GetApplication().GetSystemParameter().IgnoreSave()) {
Base::Console().Warning("System parameter file couldn't be opened.\n"
"Continue with an empty configuration that won't be saved.\n");
}
if (App::GetApplication().GetUserParameter().IgnoreSave()) {
Base::Console().Warning("User parameter file couldn't be opened.\n"
"Continue with an empty configuration that won't be saved.\n");
}
}

View File

@@ -74,6 +74,7 @@ private:
bool hiddenMainWindow() const;
void showMainWindow();
void activateWorkbench();
void checkParameters();
private:
bool loadFromPythonModule = false;