diff --git a/src/App/Application.cpp b/src/App/Application.cpp index 937be06c96..31df8e4e31 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -47,6 +47,7 @@ #include #endif +#include #include #include #include @@ -1114,6 +1115,11 @@ Application::TransactionSignaller::~TransactionSignaller() { } } +int64_t Application::applicationPid() +{ + return QCoreApplication::applicationPid(); +} + std::string Application::getHomePath() { return mConfig["AppHomePath"]; diff --git a/src/App/Application.h b/src/App/Application.h index 4f3f1e8ffa..95ec7c2c16 100644 --- a/src/App/Application.h +++ b/src/App/Application.h @@ -399,6 +399,7 @@ public: static std::map &Config(){return mConfig;} static int GetARGC(){return _argc;} static char** GetARGV(){return _argv;} + static int64_t applicationPid(); //@} /** @name Application directories */ diff --git a/src/App/Document.cpp b/src/App/Document.cpp index c3e3f921d5..4f6c29466a 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -931,18 +931,21 @@ Document::~Document() std::string Document::getTransientDirectoryName(const std::string& uuid, const std::string& filename) const { // Create a directory name of the form: {ExeName}_Doc_{UUID}_{HASH}_{PID} - std::stringstream s; + std::stringstream out; QCryptographicHash hash(QCryptographicHash::Sha1); #if QT_VERSION < QT_VERSION_CHECK(6,3,0) hash.addData(filename.c_str(), filename.size()); #else hash.addData(QByteArrayView(filename.c_str(), filename.size())); #endif - s << App::Application::getUserCachePath() << App::Application::getExecutableName() - << "_Doc_" << uuid - << "_" << hash.result().toHex().left(6).constData() - << "_" << QCoreApplication::applicationPid(); - return s.str(); + out << App::Application::getUserCachePath() << App::Application::getExecutableName() + << "_Doc_" + << uuid + << "_" + << hash.result().toHex().left(6).constData() + << "_" + << App::Application::applicationPid(); + return out.str(); } //-------------------------------------------------------------------------- diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index 32101ce3b0..08b3eb2225 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -2172,46 +2172,51 @@ void setAppNameAndIcon() void tryRunEventLoop(GUISingleApplication& mainApp) { - std::stringstream s; - s << App::Application::getUserCachePath() << App::Application::getExecutableName() << "_" - << QCoreApplication::applicationPid() << ".lock"; + std::stringstream out; + out << App::Application::getUserCachePath() + << App::Application::getExecutableName() + << "_" + << App::Application::applicationPid() + << ".lock"; + // open a lock file with the PID - Base::FileInfo fi(s.str()); + Base::FileInfo fi(out.str()); Base::ofstream lock(fi); // In case the file_lock cannot be created start FreeCAD without IPC support. #if !defined(FC_OS_WIN32) || (BOOST_VERSION < 107600) - std::string filename = s.str(); + std::string filename = out.str(); #else std::wstring filename = fi.toStdWString(); #endif - std::unique_ptr flock; try { - flock = std::make_unique(filename.c_str()); - flock->lock(); + boost::interprocess::file_lock flock(filename.c_str()); + if (flock.try_lock()) { + Base::Console().Log("Init: Executing event loop...\n"); + QApplication::exec(); + + // Qt can't handle exceptions thrown from event handlers, so we need + // to manually rethrow SystemExitExceptions. + if (mainApp.caughtException) { + throw Base::SystemExitException(*mainApp.caughtException.get()); + } + + // close the lock file, in case of a crash we can see the existing lock file + // on the next restart and try to repair the documents, if needed. + flock.unlock(); + lock.close(); + fi.deleteFile(); + } + else { + Base::Console().Warning("Failed to create a file lock for the IPC.\n" + "The application will be terminated\n"); + } } catch (const boost::interprocess::interprocess_exception& e) { QString msg = QString::fromLocal8Bit(e.what()); Base::Console().Warning("Failed to create a file lock for the IPC: %s\n", msg.toUtf8().constData()); } - - Base::Console().Log("Init: Executing event loop...\n"); - QApplication::exec(); - - // Qt can't handle exceptions thrown from event handlers, so we need - // to manually rethrow SystemExitExceptions. - if (mainApp.caughtException) { - throw Base::SystemExitException(*mainApp.caughtException.get()); - } - - // close the lock file, in case of a crash we can see the existing lock file - // on the next restart and try to repair the documents, if needed. - if (flock) { - flock->unlock(); - } - lock.close(); - fi.deleteFile(); } void runEventLoop(GUISingleApplication& mainApp) diff --git a/src/Gui/DocumentRecovery.cpp b/src/Gui/DocumentRecovery.cpp index d74fdf2016..c654f49f60 100644 --- a/src/Gui/DocumentRecovery.cpp +++ b/src/Gui/DocumentRecovery.cpp @@ -651,12 +651,12 @@ void DocumentRecoveryHandler::checkForPreviousCrashes(const std::function locks = tmp.entryInfoList(); - for (QList::iterator it = locks.begin(); it != locks.end(); ++it) { - QString bn = it->baseName(); + for (const QFileInfo& it : locks) { + QString bn = it.baseName(); // ignore the lock file for this instance - QString pid = QString::number(QCoreApplication::applicationPid()); + QString pid = QString::number(App::Application::applicationPid()); if (bn.startsWith(exeName) && bn.indexOf(pid) < 0) { - QString fn = it->absoluteFilePath(); + QString fn = it.absoluteFilePath(); #if !defined(FC_OS_WIN32) || (BOOST_VERSION < 107600) boost::interprocess::file_lock flock(fn.toUtf8()); @@ -665,7 +665,7 @@ void DocumentRecoveryHandler::checkForPreviousCrashes(const std::function dirs = tmp.entryInfoList(); - callableFunc(tmp, dirs, it->fileName()); + callableFunc(tmp, dirs, it.fileName()); + } + else { + Base::Console().Log("Failed to lock file %s\n", fn.toUtf8().constData()); } } }