From 621a492b6a2aa1c691c454894abf2ea6d65bc76f Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Wed, 27 Sep 2023 09:57:59 +0200 Subject: [PATCH] AutoTest: Guard against concurrent access While parsing for Qt Quick Tests it may happen that an internal map is accessed concurrently by different threads. Guard against this. Minor drive-by optimizations. Change-Id: Ic3b62c27feddb9a5ac5588a6c9643fc0e623ce19 Reviewed-by: David Schulz --- src/plugins/autotest/quick/quicktestparser.cpp | 15 ++++++++++----- src/plugins/autotest/quick/quicktestparser.h | 4 +++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/plugins/autotest/quick/quicktestparser.cpp b/src/plugins/autotest/quick/quicktestparser.cpp index ef0bba8cc89..017f9f4c6dd 100644 --- a/src/plugins/autotest/quick/quicktestparser.cpp +++ b/src/plugins/autotest/quick/quicktestparser.cpp @@ -261,7 +261,10 @@ bool QuickTestParser::handleQtQuickTest(QPromise &promise, return false; const FilePath cppFileName = document->filePath(); const FilePath proFile = FilePath::fromString(ppList.at(0)->projectFile); - m_mainCppFiles.insert(cppFileName, proFile); + { + QWriteLocker lock(&m_parseLock); + m_mainCppFiles.insert(cppFileName, proFile); + } const FilePath srcDir = FilePath::fromString(quickTestSrcDir(cppFileName)); if (srcDir.isEmpty()) return false; @@ -340,13 +343,13 @@ QuickTestParser::QuickTestParser(ITestFramework *framework) void QuickTestParser::init(const QSet &filesToParse, bool fullParse) { m_qmlSnapshot = QmlJSTools::Internal::ModelManager::instance()->snapshot(); + QWriteLocker lock(&m_parseLock); // should not be necessary if (!fullParse) { // in a full parse we get the correct entry points by the respective main m_proFilesForQmlFiles = QuickTestUtils::proFilesForQmlFiles(framework(), filesToParse); // get rid of cached main cpp files that are going to get processed anyhow for (const FilePath &file : filesToParse) { - if (m_mainCppFiles.contains(file)) { - m_mainCppFiles.remove(file); + if (m_mainCppFiles.remove(file) == 1) { if (m_mainCppFiles.isEmpty()) break; } @@ -355,6 +358,7 @@ void QuickTestParser::init(const QSet &filesToParse, bool fullParse) // get rid of all cached main cpp files m_mainCppFiles.clear(); } + lock.unlock(); m_checkForDerivedTests = theQtTestFramework().quickCheckForDerivedTests(); @@ -399,9 +403,10 @@ bool QuickTestParser::processDocument(QPromise &promise, return handleQtQuickTest(promise, cppdoc, framework()); } -FilePath QuickTestParser::projectFileForMainCppFile(const FilePath &fileName) const +FilePath QuickTestParser::projectFileForMainCppFile(const FilePath &fileName) { - return m_mainCppFiles.contains(fileName) ? m_mainCppFiles.value(fileName) : FilePath(); + QReadLocker lock(&m_parseLock); + return m_mainCppFiles.value(fileName); } } // namespace Autotest::Internal diff --git a/src/plugins/autotest/quick/quicktestparser.h b/src/plugins/autotest/quick/quicktestparser.h index e93fa9605f4..c22e1d480e1 100644 --- a/src/plugins/autotest/quick/quicktestparser.h +++ b/src/plugins/autotest/quick/quicktestparser.h @@ -8,6 +8,7 @@ #include #include +#include namespace Autotest { namespace Internal { @@ -28,7 +29,7 @@ public: void release() override; bool processDocument(QPromise &promise, const Utils::FilePath &fileName) override; - Utils::FilePath projectFileForMainCppFile(const Utils::FilePath &fileName) const; + Utils::FilePath projectFileForMainCppFile(const Utils::FilePath &fileName); QStringList supportedExtensions() const override { return {"qml"}; }; private: @@ -45,6 +46,7 @@ private: QMap > m_watchedFiles; QMap m_mainCppFiles; QSet m_prefilteredFiles; + QReadWriteLock m_parseLock; // guard for m_mainCppFiles bool m_checkForDerivedTests = false; };