summaryrefslogtreecommitdiff
path: root/src/plugins/cpptools
diff options
context:
space:
mode:
authorJarek Kobus <jaroslaw.kobus@qt.io>2021-03-03 15:35:34 +0100
committerJarek Kobus <jaroslaw.kobus@qt.io>2021-04-09 12:29:31 +0000
commitf4ab1279fd55a00e2bede18ec9ad283c668b46bd (patch)
treef190d4493b32ecc2f4d164b04ead04ec26150182 /src/plugins/cpptools
parent2800f3b51f70d50d2d976ee6340b71c29efd17d0 (diff)
downloadqt-creator-f4ab1279fd55a00e2bede18ec9ad283c668b46bd.tar.gz
Fix a possible crash in StringTable on shutdown
The issue is that when a GC() function is being executed in a separate thread, the main thread may delete the StringTable (on shutdown) in the same time. The destructor of StringTable didn't check in any way that the other thread is still executing GC() method. In order to fix it we employ runAsync method, returning the handle to the running task. We store the handle in futureSynchronizer, and in destructor of StringTablePrivate we safely wait for all futures to be finished. Fixes: QTCREATORBUG-25417 Change-Id: I0039d6041276c521c221e8dfc3894e84e47b82a2 Reviewed-by: Christian Stenger <christian.stenger@qt.io> Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Diffstat (limited to 'src/plugins/cpptools')
-rw-r--r--src/plugins/cpptools/stringtable.cpp31
1 files changed, 20 insertions, 11 deletions
diff --git a/src/plugins/cpptools/stringtable.cpp b/src/plugins/cpptools/stringtable.cpp
index 5122c3a8a9..7f5d0178a3 100644
--- a/src/plugins/cpptools/stringtable.cpp
+++ b/src/plugins/cpptools/stringtable.cpp
@@ -26,9 +26,11 @@
#include "stringtable.h"
#include <utils/qtcassert.h>
+#include <utils/runextensions.h>
#include <QDebug>
#include <QElapsedTimer>
+#include <QFutureSynchronizer>
#include <QMutex>
#include <QSet>
#include <QThreadPool>
@@ -48,18 +50,14 @@ class StringTablePrivate : public QObject
{
public:
StringTablePrivate();
+ ~StringTablePrivate() override { m_futureSynchronizer.waitForFinished(); }
QString insert(const QString &string);
- void startGC() { QThreadPool::globalInstance()->start(&m_gcRunner); }
+ void addFuture(const QFuture<void> &future);
+ void startGC() { addFuture(Utils::runAsync(&StringTablePrivate::GC, this)); }
void GC();
- class GCRunner: public QRunnable {
- StringTablePrivate &m_stringTable;
-
- public:
- explicit GCRunner(StringTablePrivate &stringTable): m_stringTable(stringTable) {}
- void run() override { m_stringTable.GC(); }
- } m_gcRunner;
+ QFutureSynchronizer<void> m_futureSynchronizer;
mutable QMutex m_lock;
QAtomicInt m_stopGCRequested{false};
@@ -67,15 +65,26 @@ public:
QTimer m_gcCountDown;
};
+void StringTablePrivate::addFuture(const QFuture<void> &future)
+{
+ m_futureSynchronizer.addFuture(future);
+ const QList<QFuture<void>> futures = m_futureSynchronizer.futures();
+ const int maxFuturesCount = 10;
+ if (futures.count() <= maxFuturesCount)
+ return;
+ m_futureSynchronizer.clearFutures();
+ for (const auto &future : futures) {
+ if (!future.isFinished())
+ m_futureSynchronizer.addFuture(future);
+ }
+}
+
static StringTablePrivate *m_instance = nullptr;
StringTablePrivate::StringTablePrivate()
- : m_gcRunner(*this)
{
m_strings.reserve(1000);
- m_gcRunner.setAutoDelete(false);
-
m_gcCountDown.setObjectName(QLatin1String("StringTable::m_gcCountDown"));
m_gcCountDown.setSingleShot(true);
m_gcCountDown.setInterval(GCTimeOut);