forked from qt-creator/qt-creator
LSP: use asynchronous shutdown for running servers
Change-Id: I3b1853177d07c98e051de0bc9f494389fbf4c104 Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
@@ -82,8 +82,7 @@ LanguageClientManager::LanguageClientManager()
|
|||||||
|
|
||||||
LanguageClientManager::~LanguageClientManager()
|
LanguageClientManager::~LanguageClientManager()
|
||||||
{
|
{
|
||||||
for (auto interface : Utils::filtered(m_clients, &BaseClient::reachable))
|
QTC_ASSERT(m_clients.isEmpty(), qDeleteAll(m_clients));
|
||||||
interface->shutdown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LanguageClientManager::init()
|
void LanguageClientManager::init()
|
||||||
@@ -168,6 +167,8 @@ void LanguageClientManager::removeMarks(const Core::Id &id)
|
|||||||
|
|
||||||
void LanguageClientManager::startClient(LanguageClientSettings setting)
|
void LanguageClientManager::startClient(LanguageClientSettings setting)
|
||||||
{
|
{
|
||||||
|
if (managerInstance->m_shuttingDown)
|
||||||
|
return;
|
||||||
auto client = new StdIOClient(setting.m_executable, setting.m_arguments);
|
auto client = new StdIOClient(setting.m_executable, setting.m_arguments);
|
||||||
client->setName(setting.m_name);
|
client->setName(setting.m_name);
|
||||||
if (setting.m_mimeType != noLanguageFilter)
|
if (setting.m_mimeType != noLanguageFilter)
|
||||||
@@ -177,6 +178,10 @@ void LanguageClientManager::startClient(LanguageClientSettings setting)
|
|||||||
|
|
||||||
void LanguageClientManager::startClient(BaseClient *client)
|
void LanguageClientManager::startClient(BaseClient *client)
|
||||||
{
|
{
|
||||||
|
if (managerInstance->m_shuttingDown) {
|
||||||
|
managerInstance->clientFinished(client);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!managerInstance->m_clients.contains(client))
|
if (!managerInstance->m_clients.contains(client))
|
||||||
managerInstance->m_clients.append(client);
|
managerInstance->m_clients.append(client);
|
||||||
connect(client, &BaseClient::finished, managerInstance, [client](){
|
connect(client, &BaseClient::finished, managerInstance, [client](){
|
||||||
@@ -215,6 +220,20 @@ void LanguageClientManager::deleteClient(BaseClient *client)
|
|||||||
delete 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<BaseClient *> LanguageClientManager::reachableClients()
|
QVector<BaseClient *> LanguageClientManager::reachableClients()
|
||||||
{
|
{
|
||||||
return Utils::filtered(m_clients, &BaseClient::reachable);
|
return Utils::filtered(m_clients, &BaseClient::reachable);
|
||||||
@@ -236,15 +255,17 @@ void LanguageClientManager::clientFinished(BaseClient *client)
|
|||||||
constexpr int restartTimeoutS = 5;
|
constexpr int restartTimeoutS = 5;
|
||||||
const bool unexpectedFinish = client->state() != BaseClient::Shutdown
|
const bool unexpectedFinish = client->state() != BaseClient::Shutdown
|
||||||
&& client->state() != BaseClient::ShutdownRequested;
|
&& client->state() != BaseClient::ShutdownRequested;
|
||||||
if (unexpectedFinish) {
|
if (unexpectedFinish && !m_shuttingDown) {
|
||||||
managerInstance->removeMarks(client->id());
|
removeMarks(client->id());
|
||||||
client->disconnect(managerInstance);
|
client->disconnect(this);
|
||||||
client->log(tr("Unexpectedly finished. Restarting in %1 seconds.").arg(restartTimeoutS),
|
client->log(tr("Unexpectedly finished. Restarting in %1 seconds.").arg(restartTimeoutS),
|
||||||
Core::MessageManager::Flash);
|
Core::MessageManager::Flash);
|
||||||
client->reset();
|
client->reset();
|
||||||
QTimer::singleShot(restartTimeoutS * 1000, this, [client](){ startClient(client); });
|
QTimer::singleShot(restartTimeoutS * 1000, client, [client](){ startClient(client); });
|
||||||
} else {
|
} else {
|
||||||
deleteClient(client);
|
deleteClient(client);
|
||||||
|
if (m_shuttingDown && m_clients.isEmpty())
|
||||||
|
emit shutdownFinished();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,6 +70,13 @@ public:
|
|||||||
|
|
||||||
static void deleteClient(BaseClient *client);
|
static void deleteClient(BaseClient *client);
|
||||||
|
|
||||||
|
static void shutdown();
|
||||||
|
|
||||||
|
static LanguageClientManager *instance();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void shutdownFinished();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LanguageClientManager();
|
LanguageClientManager();
|
||||||
LanguageClientManager(const LanguageClientManager &other) = delete;
|
LanguageClientManager(const LanguageClientManager &other) = delete;
|
||||||
@@ -90,6 +97,7 @@ private:
|
|||||||
|
|
||||||
void clientFinished(BaseClient *client);
|
void clientFinished(BaseClient *client);
|
||||||
|
|
||||||
|
bool m_shuttingDown = false;
|
||||||
QVector<BaseClient *> m_clients;
|
QVector<BaseClient *> m_clients;
|
||||||
QHash<Utils::FileName, QHash<Core::Id, QVector<LanguageClientMark *>>> m_marks;
|
QHash<Utils::FileName, QHash<Core::Id, QVector<LanguageClientMark *>>> m_marks;
|
||||||
QHash<LanguageServerProtocol::MessageId, QList<BaseClient *>> m_exclusiveRequests;
|
QHash<LanguageServerProtocol::MessageId, QList<BaseClient *>> m_exclusiveRequests;
|
||||||
|
|||||||
@@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
#include "languageclientplugin.h"
|
#include "languageclientplugin.h"
|
||||||
|
|
||||||
|
#include "baseclient.h"
|
||||||
|
|
||||||
namespace LanguageClient {
|
namespace LanguageClient {
|
||||||
|
|
||||||
bool LanguageClientPlugin::initialize(const QStringList & /*arguments*/, QString * /*errorString*/)
|
bool LanguageClientPlugin::initialize(const QStringList & /*arguments*/, QString * /*errorString*/)
|
||||||
@@ -38,4 +40,14 @@ void LanguageClientPlugin::extensionsInitialized()
|
|||||||
LanguageClientSettings::init();
|
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
|
} // namespace LanguageClient
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
bool initialize(const QStringList &arguments, QString *errorString) override;
|
bool initialize(const QStringList &arguments, QString *errorString) override;
|
||||||
void extensionsInitialized() override;
|
void extensionsInitialized() override;
|
||||||
|
ShutdownFlag aboutToShutdown() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LanguageClientManager m_clientManager;
|
LanguageClientManager m_clientManager;
|
||||||
|
|||||||
Reference in New Issue
Block a user