diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index 32101ce3b08f..5649818b7552 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -23,13 +23,13 @@ #include "PreCompiled.h" #ifndef _PreComp_ -#include #include #include #include #include #include #include +#include #include #include #include @@ -2172,46 +2172,35 @@ void setAppNameAndIcon() void tryRunEventLoop(GUISingleApplication& mainApp) { - std::stringstream s; - s << App::Application::getUserCachePath() << App::Application::getExecutableName() << "_" - << QCoreApplication::applicationPid() << ".lock"; - // open a lock file with the PID - Base::FileInfo fi(s.str()); - Base::ofstream lock(fi); + std::stringstream out; + out << App::Application::getUserCachePath() + << App::Application::getExecutableName() + << "_" + << QCoreApplication::applicationPid() + << ".lock"; - // 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(); -#else - std::wstring filename = fi.toStdWString(); -#endif - std::unique_ptr flock; - try { - flock = std::make_unique(filename.c_str()); - flock->lock(); - } - 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()); - } + // open a lock file with the PID + QString filename = QString::fromStdString(out.str()); + QLockFile flock(filename); + if (flock.tryLock()) { + Base::Console().Log("Init: Executing event loop...\n"); + QApplication::exec(); - 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()); + } - // 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(); } + else { + Base::Console().Warning("Failed to create a file lock for the IPC.\n" + "The application will be terminated\n"); - // 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) @@ -2475,24 +2464,17 @@ void Application::checkForDeprecatedSettings() void Application::checkForPreviousCrashes() { - try { - Gui::Dialog::DocumentRecoveryFinder finder; - if (!finder.checkForPreviousCrashes()) { - - // If the recovery dialog wasn't shown check the cache size periodically - Gui::Dialog::ApplicationCache cache; - cache.applyUserSettings(); - if (cache.periodicCheckOfSize()) { - qint64 total = cache.size(); - cache.performAction(total); - } + Gui::Dialog::DocumentRecoveryFinder finder; + if (!finder.checkForPreviousCrashes()) { + + // If the recovery dialog wasn't shown check the cache size periodically + Gui::Dialog::ApplicationCache cache; + cache.applyUserSettings(); + if (cache.periodicCheckOfSize()) { + qint64 total = cache.size(); + cache.performAction(total); } } - catch (const boost::interprocess::interprocess_exception& e) { - QString msg = QString::fromLocal8Bit(e.what()); - Base::Console().Warning("Failed check for previous crashes because of IPC error: %s\n", - msg.toUtf8().constData()); - } } App::Document* Application::reopen(App::Document* doc) diff --git a/src/Gui/DocumentRecovery.cpp b/src/Gui/DocumentRecovery.cpp index d74fdf201672..ceb4d6f09f02 100644 --- a/src/Gui/DocumentRecovery.cpp +++ b/src/Gui/DocumentRecovery.cpp @@ -27,7 +27,6 @@ #include "PreCompiled.h" #ifndef _PreComp_ -# include # include # include # include @@ -37,6 +36,7 @@ # include # include # include +# include # include # include # include @@ -584,45 +584,35 @@ bool DocumentRecoveryFinder::checkForPreviousCrashes() void DocumentRecoveryFinder::checkDocumentDirs(QDir& tmp, const QList& dirs, const QString& fn) { - if (dirs.isEmpty()) { - // delete the lock file immediately if no transient directories are related - tmp.remove(fn); - } - else { - int countDeletedDocs = 0; - QString recovery_files = QString::fromLatin1("fc_recovery_files"); - for (QList::const_iterator it = dirs.cbegin(); it != dirs.cend(); ++it) { - QDir doc_dir(it->absoluteFilePath()); - doc_dir.setFilter(QDir::NoDotAndDotDot|QDir::AllEntries); - uint entries = doc_dir.entryList().count(); - if (entries == 0) { - // in this case we can delete the transient directory because - // we cannot do anything - if (tmp.rmdir(it->filePath())) - countDeletedDocs++; - } - // search for the existence of a recovery file - else if (doc_dir.exists(QLatin1String("fc_recovery_file.xml"))) { - // store the transient directory in case it's not empty - restoreDocFiles << *it; - } - // search for the 'fc_recovery_files' sub-directory and check that it's the only entry - else if (entries == 1 && doc_dir.exists(recovery_files)) { - // if the sub-directory is empty delete the transient directory - QDir rec_dir(doc_dir.absoluteFilePath(recovery_files)); - rec_dir.setFilter(QDir::NoDotAndDotDot|QDir::AllEntries); - if (rec_dir.entryList().isEmpty()) { - doc_dir.rmdir(recovery_files); - if (tmp.rmdir(it->filePath())) - countDeletedDocs++; - } - } + Q_UNUSED(fn) + + QString recovery_files = QString::fromLatin1("fc_recovery_files"); + for (QList::const_iterator it = dirs.cbegin(); it != dirs.cend(); ++it) { +Base::Console().Warning("File: %s\n", it->absoluteFilePath().toUtf8().constData()); + QDir doc_dir(it->absoluteFilePath()); + doc_dir.setFilter(QDir::NoDotAndDotDot|QDir::AllEntries); + uint entries = doc_dir.entryList().count(); + if (entries == 0) { + // in this case we can delete the transient directory because + // we cannot do anything + bool ok = tmp.rmdir(it->filePath()); +Base::Console().Warning("Delete %s\n", (ok ? "OK" : "Failed")); } - - // all directories corresponding to the lock file have been deleted - // so delete the lock file, too - if (countDeletedDocs == dirs.size()) { - tmp.remove(fn); + // search for the existence of a recovery file + else if (doc_dir.exists(QLatin1String("fc_recovery_file.xml"))) { + // store the transient directory in case it's not empty + restoreDocFiles << *it; + } + // search for the 'fc_recovery_files' sub-directory and check that it's the only entry + else if (entries == 1 && doc_dir.exists(recovery_files)) { + // if the sub-directory is empty delete the transient directory + QDir rec_dir(doc_dir.absoluteFilePath(recovery_files)); + rec_dir.setFilter(QDir::NoDotAndDotDot|QDir::AllEntries); + if (rec_dir.entryList().isEmpty()) { + doc_dir.rmdir(recovery_files); + bool ok = tmp.rmdir(it->filePath()); +Base::Console().Warning("Delete %s\n", (ok ? "OK" : "Failed")); + } } } } @@ -651,21 +641,17 @@ 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()); 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()); -#else - boost::interprocess::file_lock flock(fn.toStdWString().c_str()); -#endif - if (flock.try_lock()) { + QLockFile flock(fn); + if (flock.tryLock()) { // OK, this file is a leftover from a previous crash - QString crashed_pid = bn.mid(exeName.length()+1); + QString crashed_pid = bn.mid(exeName.length() + 1); // search for transient directories with this PID QString filter; QTextStream str(&filter); @@ -674,7 +660,10 @@ void DocumentRecoveryHandler::checkForPreviousCrashes(const std::function dirs = tmp.entryInfoList(); - callableFunc(tmp, dirs, it->fileName()); + callableFunc(tmp, dirs, it.fileName()); + } + else { + Base::Console().Message("Cannot lock %s\n", fn.toUtf8().constData()); } } } diff --git a/src/Gui/QtAll.h b/src/Gui/QtAll.h index 0bb24bdc1d82..1beba0bb2bb5 100644 --- a/src/Gui/QtAll.h +++ b/src/Gui/QtAll.h @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include