From f2004660668895eb7858f89a9cc26acea5474013 Mon Sep 17 00:00:00 2001 From: Jarek Kobus Date: Tue, 16 Feb 2021 02:26:21 +0100 Subject: [PATCH] ClassView: Stop the running timer in Parser thread on close When we are going to delete Parser object, it may happen, that its timer is still being active. A call to parserThread.quit() won't stop the timer. When we quit the thread and wait for it to finish, the thread's timer may still be active. Then we delete the Parser in the main thread, what cause the following warning to appear: "QObject::killTimer: Timers cannot be stopped from another thread". In order to fix it, we post a request to the parser's thread for stopping the timer by a call to aboutToShutdown() with Qt::BlockingQueuedConnection, just before quitting the thread, as the thread's event loop should still be spinning and is able to receive and handle our request. It's the only safe way to stop the active timer that was started in another thread - it must be stopped it the same thread it was started in. Inside the call to aboutToShutdown() we mark that we don't want to start the timer anymore with m_shuttingDown flag and we stop the timer. After the blocking call returns to the main thread we are sure that the timer is not active anymore and it won't became active in the future, so we safely quit the thread and delete the timer. Task-number: QTCREATORBUG-25317 Change-Id: I3b95c062b5561588c45c223d8588b2b700ad4040 Reviewed-by: Christian Kandeler --- src/plugins/classview/classviewmanager.cpp | 1 + src/plugins/classview/classviewparser.cpp | 10 ++++++++-- src/plugins/classview/classviewparser.h | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/plugins/classview/classviewmanager.cpp b/src/plugins/classview/classviewmanager.cpp index 8284071d217..338c1eb3578 100644 --- a/src/plugins/classview/classviewmanager.cpp +++ b/src/plugins/classview/classviewmanager.cpp @@ -123,6 +123,7 @@ Manager::Manager(QObject *parent) Manager::~Manager() { + QMetaObject::invokeMethod(&d->parser, &Parser::aboutToShutdown, Qt::BlockingQueuedConnection); d->parserThread.quit(); d->parserThread.wait(); delete d; diff --git a/src/plugins/classview/classviewparser.cpp b/src/plugins/classview/classviewparser.cpp index 63f3048862f..49af9de8767 100644 --- a/src/plugins/classview/classviewparser.cpp +++ b/src/plugins/classview/classviewparser.cpp @@ -89,6 +89,7 @@ public: CPlusPlus::Document::Ptr document(const QString &fileName) const; QTimer timer; + bool m_shuttingDown = false; struct DocumentCache { unsigned treeRevision = 0; @@ -199,6 +200,12 @@ void Parser::setFlatMode(bool flatMode) requestCurrentState(); } +void Parser::aboutToShutdown() +{ + d->m_shuttingDown = true; + d->timer.stop(); +} + /*! Returns the internal tree item for \a item. \a skipRoot skips the root item. @@ -405,9 +412,8 @@ void Parser::parseDocument(const CPlusPlus::Document::Ptr &doc) getParseDocumentTree(doc); - if (!d->timer.isActive()) + if (!d->timer.isActive() && !d->m_shuttingDown) d->timer.start(400); //! Delay in msecs before an update - return; } /*! diff --git a/src/plugins/classview/classviewparser.h b/src/plugins/classview/classviewparser.h index 65299e87b13..4d6f75f8fa1 100644 --- a/src/plugins/classview/classviewparser.h +++ b/src/plugins/classview/classviewparser.h @@ -62,6 +62,7 @@ public: void resetDataToCurrentState(); void parseDocument(const CPlusPlus::Document::Ptr &doc); void setFlatMode(bool flat); + void aboutToShutdown(); signals: void treeDataUpdate(QSharedPointer result);