From 7c0c98a43870e26be86e69d05a6ba85fcd3c593d Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Wed, 10 Feb 2021 13:17:54 +0100 Subject: [PATCH] Locator: Do not block main event loop There are multiple locator filters (SpotlightLocatorFilter, JavaScriptFilter, HelpIndexFilter, the LanguageClient filters) that depend on the main event loop, and might lock up if that does not run anymore. So we cannot use waitForFinished. Cancel a running locator search, and tell the plugin manager that we need to wait for asynchronous events to finish before shutting down. Amends cb5977fbad51d035d05f441e78204f591a5a916f Change-Id: Id0b3dc75bc22f21b34be39c3bdbec915b60bdee6 Reviewed-by: Jarek Kobus --- src/plugins/coreplugin/coreplugin.cpp | 5 ++-- src/plugins/coreplugin/locator/locator.cpp | 5 ++-- src/plugins/coreplugin/locator/locator.h | 7 ++++-- .../coreplugin/locator/locatorwidget.cpp | 24 +++++++++++++------ .../coreplugin/locator/locatorwidget.h | 13 +++++++--- 5 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/plugins/coreplugin/coreplugin.cpp b/src/plugins/coreplugin/coreplugin.cpp index a98eaa65a3c..2803793229a 100644 --- a/src/plugins/coreplugin/coreplugin.cpp +++ b/src/plugins/coreplugin/coreplugin.cpp @@ -443,7 +443,8 @@ QString CorePlugin::msgCrashpadInformation() ExtensionSystem::IPlugin::ShutdownFlag CorePlugin::aboutToShutdown() { Find::aboutToShutdown(); - m_locator->aboutToShutdown(); + ExtensionSystem::IPlugin::ShutdownFlag shutdownFlag = m_locator->aboutToShutdown( + [this] { emit asynchronousShutdownFinished(); }); m_mainWindow->aboutToShutdown(); - return SynchronousShutdown; + return shutdownFlag; } diff --git a/src/plugins/coreplugin/locator/locator.cpp b/src/plugins/coreplugin/locator/locator.cpp index ac75bac73eb..2d383d2da99 100644 --- a/src/plugins/coreplugin/locator/locator.cpp +++ b/src/plugins/coreplugin/locator/locator.cpp @@ -169,7 +169,8 @@ bool Locator::delayedInitialize() return true; } -void Locator::aboutToShutdown() +ExtensionSystem::IPlugin::ShutdownFlag Locator::aboutToShutdown( + const std::function &emitAsynchronousShutdownFinished) { m_shuttingDown = true; m_refreshTimer.stop(); @@ -177,7 +178,7 @@ void Locator::aboutToShutdown() m_refreshTask.cancel(); m_refreshTask.waitForFinished(); } - emit aboutToShutdownOccurred(); + return LocatorWidget::aboutToShutdown(emitAsynchronousShutdownFinished); } void Locator::loadSettings() diff --git a/src/plugins/coreplugin/locator/locator.h b/src/plugins/coreplugin/locator/locator.h index 1f3c7ece6da..95a6b63687b 100644 --- a/src/plugins/coreplugin/locator/locator.h +++ b/src/plugins/coreplugin/locator/locator.h @@ -29,11 +29,14 @@ #include "locatorconstants.h" #include +#include #include #include #include +#include + namespace Core { namespace Internal { @@ -48,7 +51,8 @@ public: ~Locator() override; static Locator *instance(); - void aboutToShutdown(); + ExtensionSystem::IPlugin::ShutdownFlag aboutToShutdown( + const std::function &emitAsynchronousShutdownFinished); void initialize(); void extensionsInitialized(); @@ -63,7 +67,6 @@ public: signals: void filtersChanged(); - void aboutToShutdownOccurred(); public slots: void refresh(QList filters); diff --git a/src/plugins/coreplugin/locator/locatorwidget.cpp b/src/plugins/coreplugin/locator/locatorwidget.cpp index 09c1f331bce..2bf34b710b6 100644 --- a/src/plugins/coreplugin/locator/locatorwidget.cpp +++ b/src/plugins/coreplugin/locator/locatorwidget.cpp @@ -72,6 +72,7 @@ const int LocatorEntryRole = int(HighlightingItemRole::User); namespace Core { namespace Internal { +bool LocatorWidget::m_shuttingDown = false; QFuture LocatorWidget::m_sharedFuture; LocatorWidget *LocatorWidget::m_sharedFutureOrigin = nullptr; @@ -619,13 +620,6 @@ LocatorWidget::LocatorWidget(Locator *locator) : connect(qApp, &QApplication::focusChanged, this, &LocatorWidget::updatePreviousFocusWidget); connect(locator, &Locator::filtersChanged, this, &LocatorWidget::updateFilterList); - connect(locator, &Locator::aboutToShutdownOccurred, this, [this]() { - m_shuttingDown = true; - if (m_entriesWatcher->isRunning()) { - m_entriesWatcher->cancel(); - m_entriesWatcher->waitForFinished(); - } - }); updateFilterList(); } @@ -912,6 +906,22 @@ void LocatorWidget::scheduleAcceptEntry(const QModelIndex &index) } } +ExtensionSystem::IPlugin::ShutdownFlag LocatorWidget::aboutToShutdown( + const std::function &emitAsynchronousShutdownFinished) +{ + m_shuttingDown = true; + if (m_sharedFuture.isRunning()) { + Utils::onFinished(m_sharedFuture, + Locator::instance(), + [emitAsynchronousShutdownFinished](const QFuture &) { + emitAsynchronousShutdownFinished(); + }); + m_sharedFuture.cancel(); + return ExtensionSystem::IPlugin::AsynchronousShutdown; + } + return ExtensionSystem::IPlugin::SynchronousShutdown; +} + void LocatorWidget::acceptEntry(int row) { if (row < 0 || row >= m_locatorModel->rowCount()) diff --git a/src/plugins/coreplugin/locator/locatorwidget.h b/src/plugins/coreplugin/locator/locatorwidget.h index 38ff7585add..96aca416603 100644 --- a/src/plugins/coreplugin/locator/locatorwidget.h +++ b/src/plugins/coreplugin/locator/locatorwidget.h @@ -27,12 +27,15 @@ #include "locator.h" +#include #include #include #include #include +#include + QT_BEGIN_NAMESPACE class QAbstractItemModel; class QAction; @@ -63,6 +66,9 @@ public: void scheduleAcceptEntry(const QModelIndex &index); + static ExtensionSystem::IPlugin::ShutdownFlag aboutToShutdown( + const std::function &emitAsynchronousShutdownFinished); + signals: void showCurrentItemToolTip(); void lostFocus(); @@ -91,16 +97,17 @@ private: LocatorModel *m_locatorModel = nullptr; + static bool m_shuttingDown; + static QFuture m_sharedFuture; + static LocatorWidget *m_sharedFutureOrigin; + QMenu *m_filterMenu = nullptr; QAction *m_refreshAction = nullptr; QAction *m_configureAction = nullptr; Utils::FancyLineEdit *m_fileLineEdit = nullptr; QTimer m_showPopupTimer; QFutureWatcher *m_entriesWatcher = nullptr; - static QFuture m_sharedFuture; - static LocatorWidget *m_sharedFutureOrigin; QString m_requestedCompletionText; - bool m_shuttingDown = false; bool m_needsClearResult = true; bool m_updateRequested = false; bool m_rerunAfterFinished = false;