diff --git a/src/core/toolsupport.cpp b/src/core/toolsupport.cpp index febb97fb..5622d922 100644 --- a/src/core/toolsupport.cpp +++ b/src/core/toolsupport.cpp @@ -1,5 +1,7 @@ #include "toolsupport.hpp" +#include +#include #include #include #include @@ -28,6 +30,10 @@ bool QmlToolingSupport::updateTooling(const QDir& configRoot, QmlScanner& scanne return false; } + if (!QmlToolingSupport::lockTooling()) { + return false; + } + if (!QmlToolingSupport::updateQmllsConfig(configRoot, false)) { QDir(vfs->filePath("qs")).removeRecursively(); return false; @@ -37,6 +43,39 @@ bool QmlToolingSupport::updateTooling(const QDir& configRoot, QmlScanner& scanne return true; } +bool QmlToolingSupport::lockTooling() { + if (QmlToolingSupport::toolingLock) return true; + + auto lockPath = QsPaths::instance()->shellVfsDir()->filePath("tooling.lock"); + auto* file = new QFile(lockPath); + + if (!file->open(QFile::WriteOnly)) { + qCCritical(logTooling) << "Could not open tooling lock for write"; + return false; + } + + auto lock = flock { + .l_type = F_WRLCK, + .l_whence = SEEK_SET, // NOLINT (fcntl.h??) + .l_start = 0, + .l_len = 0, + .l_pid = 0, + }; + + if (fcntl(file->handle(), F_SETLK, &lock) == 0) { + qCInfo(logTooling) << "Acquired tooling support lock"; + QmlToolingSupport::toolingLock = file; + return true; + } else if (errno == EACCES || errno == EAGAIN) { + qCInfo(logTooling) << "Tooling support locked by another instance"; + return false; + } else { + qCCritical(logTooling).nospace() << "Could not create tooling lock at " << lockPath + << " with error code " << errno << ": " << qt_error_string(); + return false; + } +} + QString QmlToolingSupport::getQmllsConfig() { static auto config = []() { QList importPaths; diff --git a/src/core/toolsupport.hpp b/src/core/toolsupport.hpp index 0aee9c5c..9fb79216 100644 --- a/src/core/toolsupport.hpp +++ b/src/core/toolsupport.hpp @@ -12,9 +12,11 @@ public: private: static QString getQmllsConfig(); + static bool lockTooling(); static bool updateQmllsConfig(const QDir& configRoot, bool create); static void updateToolingFs(QmlScanner& scanner, const QDir& scanDir, const QDir& linkDir); static inline bool toolingEnabled = false; + static inline QFile* toolingLock = nullptr; }; } // namespace qs::core