Skip to content

Commit 78e3874

Browse files
committed
tooling: add per-shell tooling lock to prevent races
1 parent 986749c commit 78e3874

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

src/core/toolsupport.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "toolsupport.hpp"
2+
#include <cerrno>
23

4+
#include <fcntl.h>
35
#include <qcontainerfwd.h>
46
#include <qdebug.h>
57
#include <qdir.h>
@@ -28,6 +30,10 @@ bool QmlToolingSupport::updateTooling(const QDir& configRoot, QmlScanner& scanne
2830
return false;
2931
}
3032

33+
if (!QmlToolingSupport::lockTooling()) {
34+
return false;
35+
}
36+
3137
if (!QmlToolingSupport::updateQmllsConfig(configRoot, false)) {
3238
QDir(vfs->filePath("qs")).removeRecursively();
3339
return false;
@@ -37,6 +43,39 @@ bool QmlToolingSupport::updateTooling(const QDir& configRoot, QmlScanner& scanne
3743
return true;
3844
}
3945

46+
bool QmlToolingSupport::lockTooling() {
47+
if (QmlToolingSupport::toolingLock) return true;
48+
49+
auto lockPath = QsPaths::instance()->shellVfsDir()->filePath("tooling.lock");
50+
auto* file = new QFile(lockPath);
51+
52+
if (!file->open(QFile::WriteOnly)) {
53+
qCCritical(logTooling) << "Could not open tooling lock for write";
54+
return false;
55+
}
56+
57+
auto lock = flock {
58+
.l_type = F_WRLCK,
59+
.l_whence = SEEK_SET, // NOLINT (fcntl.h??)
60+
.l_start = 0,
61+
.l_len = 0,
62+
.l_pid = 0,
63+
};
64+
65+
if (fcntl(file->handle(), F_SETLK, &lock) == 0) {
66+
qCInfo(logTooling) << "Acquired tooling support lock";
67+
QmlToolingSupport::toolingLock = file;
68+
return true;
69+
} else if (errno == EACCES || errno == EAGAIN) {
70+
qCInfo(logTooling) << "Tooling support locked by another instance";
71+
return false;
72+
} else {
73+
qCCritical(logTooling).nospace() << "Could not create tooling lock at " << lockPath
74+
<< " with error code " << errno << ": " << qt_error_string();
75+
return false;
76+
}
77+
}
78+
4079
QString QmlToolingSupport::getQmllsConfig() {
4180
static auto config = []() {
4281
QList<QString> importPaths;

src/core/toolsupport.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ class QmlToolingSupport {
1212

1313
private:
1414
static QString getQmllsConfig();
15+
static bool lockTooling();
1516
static bool updateQmllsConfig(const QDir& configRoot, bool create);
1617
static void updateToolingFs(QmlScanner& scanner, const QDir& scanDir, const QDir& linkDir);
1718
static inline bool toolingEnabled = false;
19+
static inline QFile* toolingLock = nullptr;
1820
};
1921

2022
} // namespace qs::core

0 commit comments

Comments
 (0)