From 5ef4530b8f30e3f33381292ef45fb0b358efcadc Mon Sep 17 00:00:00 2001 From: David Schulz Date: Thu, 13 Sep 2018 15:31:00 +0200 Subject: [PATCH] LSP: use asynchronous shutdown for running servers Change-Id: I3b1853177d07c98e051de0bc9f494389fbf4c104 Reviewed-by: Eike Ziller --- .../languageclient/languageclientmanager.cpp | 33 +++++++++++++++---- .../languageclient/languageclientmanager.h | 8 +++++ .../languageclient/languageclientplugin.cpp | 12 +++++++ .../languageclient/languageclientplugin.h | 1 + 4 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/plugins/languageclient/languageclientmanager.cpp b/src/plugins/languageclient/languageclientmanager.cpp index c8f7b97f550..c96fa2e1ef0 100644 --- a/src/plugins/languageclient/languageclientmanager.cpp +++ b/src/plugins/languageclient/languageclientmanager.cpp @@ -82,8 +82,7 @@ LanguageClientManager::LanguageClientManager() LanguageClientManager::~LanguageClientManager() { - for (auto interface : Utils::filtered(m_clients, &BaseClient::reachable)) - interface->shutdown(); + QTC_ASSERT(m_clients.isEmpty(), qDeleteAll(m_clients)); } void LanguageClientManager::init() @@ -168,6 +167,8 @@ void LanguageClientManager::removeMarks(const Core::Id &id) void LanguageClientManager::startClient(LanguageClientSettings setting) { + if (managerInstance->m_shuttingDown) + return; auto client = new StdIOClient(setting.m_executable, setting.m_arguments); client->setName(setting.m_name); if (setting.m_mimeType != noLanguageFilter) @@ -177,6 +178,10 @@ void LanguageClientManager::startClient(LanguageClientSettings setting) void LanguageClientManager::startClient(BaseClient *client) { + if (managerInstance->m_shuttingDown) { + managerInstance->clientFinished(client); + return; + } if (!managerInstance->m_clients.contains(client)) managerInstance->m_clients.append(client); connect(client, &BaseClient::finished, managerInstance, [client](){ @@ -215,6 +220,20 @@ void LanguageClientManager::deleteClient(BaseClient *client) delete client; } +void LanguageClientManager::shutdown() +{ + if (managerInstance->m_shuttingDown) + return; + managerInstance->m_shuttingDown = true; + for (auto interface : managerInstance->m_clients) + interface->shutdown(); +} + +LanguageClientManager *LanguageClientManager::instance() +{ + return managerInstance; +} + QVector LanguageClientManager::reachableClients() { return Utils::filtered(m_clients, &BaseClient::reachable); @@ -236,15 +255,17 @@ void LanguageClientManager::clientFinished(BaseClient *client) constexpr int restartTimeoutS = 5; const bool unexpectedFinish = client->state() != BaseClient::Shutdown && client->state() != BaseClient::ShutdownRequested; - if (unexpectedFinish) { - managerInstance->removeMarks(client->id()); - client->disconnect(managerInstance); + if (unexpectedFinish && !m_shuttingDown) { + removeMarks(client->id()); + client->disconnect(this); client->log(tr("Unexpectedly finished. Restarting in %1 seconds.").arg(restartTimeoutS), Core::MessageManager::Flash); client->reset(); - QTimer::singleShot(restartTimeoutS * 1000, this, [client](){ startClient(client); }); + QTimer::singleShot(restartTimeoutS * 1000, client, [client](){ startClient(client); }); } else { deleteClient(client); + if (m_shuttingDown && m_clients.isEmpty()) + emit shutdownFinished(); } } diff --git a/src/plugins/languageclient/languageclientmanager.h b/src/plugins/languageclient/languageclientmanager.h index a00c86858ed..b15deca0f6a 100644 --- a/src/plugins/languageclient/languageclientmanager.h +++ b/src/plugins/languageclient/languageclientmanager.h @@ -70,6 +70,13 @@ public: static void deleteClient(BaseClient *client); + static void shutdown(); + + static LanguageClientManager *instance(); + +signals: + void shutdownFinished(); + private: LanguageClientManager(); LanguageClientManager(const LanguageClientManager &other) = delete; @@ -90,6 +97,7 @@ private: void clientFinished(BaseClient *client); + bool m_shuttingDown = false; QVector m_clients; QHash>> m_marks; QHash> m_exclusiveRequests; diff --git a/src/plugins/languageclient/languageclientplugin.cpp b/src/plugins/languageclient/languageclientplugin.cpp index 4fd3cedfcf8..53a0252592a 100644 --- a/src/plugins/languageclient/languageclientplugin.cpp +++ b/src/plugins/languageclient/languageclientplugin.cpp @@ -25,6 +25,8 @@ #include "languageclientplugin.h" +#include "baseclient.h" + namespace LanguageClient { bool LanguageClientPlugin::initialize(const QStringList & /*arguments*/, QString * /*errorString*/) @@ -38,4 +40,14 @@ void LanguageClientPlugin::extensionsInitialized() LanguageClientSettings::init(); } +ExtensionSystem::IPlugin::ShutdownFlag LanguageClientPlugin::aboutToShutdown() +{ + LanguageClientManager::shutdown(); + if (LanguageClientManager::clients().isEmpty()) + return ExtensionSystem::IPlugin::SynchronousShutdown; + connect(LanguageClientManager::instance(), &LanguageClientManager::shutdownFinished, + this, &ExtensionSystem::IPlugin::asynchronousShutdownFinished); + return ExtensionSystem::IPlugin::AsynchronousShutdown; +} + } // namespace LanguageClient diff --git a/src/plugins/languageclient/languageclientplugin.h b/src/plugins/languageclient/languageclientplugin.h index 31a4c1ae99b..5b34c049a7e 100644 --- a/src/plugins/languageclient/languageclientplugin.h +++ b/src/plugins/languageclient/languageclientplugin.h @@ -43,6 +43,7 @@ public: private: bool initialize(const QStringList &arguments, QString *errorString) override; void extensionsInitialized() override; + ShutdownFlag aboutToShutdown() override; private: LanguageClientManager m_clientManager;