forked from qt-creator/qt-creator
Control the lifetime of SshProcessManager
Make it possible to control when the SshProcessManager is being constructed / destructed. Expose public constructor. Since different singletons depend on each other, we need to control the order of creation and destruction of them. The order of creation is like that: 1. QCoreApplication 2. ProcessReaper 3. ProcessLauncher 4. SshConnectionManager The order of destruction must be opposite to the above. Change-Id: Ice07eb751cd61c03cb461816fa1b74ab040a53de Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -8,7 +8,7 @@ install(
|
|||||||
|
|
||||||
add_qtc_executable(qtcreator
|
add_qtc_executable(qtcreator
|
||||||
DEFINES IDE_LIBRARY_BASENAME=\"${IDE_LIBRARY_BASE_PATH}\"
|
DEFINES IDE_LIBRARY_BASENAME=\"${IDE_LIBRARY_BASE_PATH}\"
|
||||||
DEPENDS Aggregation ExtensionSystem Qt5::Core Qt5::Widgets Utils shared_qtsingleapplication app_version
|
DEPENDS Aggregation ExtensionSystem Qt5::Core Qt5::Widgets Utils QtcSsh shared_qtsingleapplication app_version
|
||||||
SOURCES
|
SOURCES
|
||||||
main.cpp
|
main.cpp
|
||||||
../tools/qtcreatorcrashhandler/crashhandlersetup.cpp ../tools/qtcreatorcrashhandler/crashhandlersetup.h
|
../tools/qtcreatorcrashhandler/crashhandlersetup.cpp ../tools/qtcreatorcrashhandler/crashhandlersetup.h
|
||||||
|
@@ -17,7 +17,7 @@ include(../rpath.pri)
|
|||||||
|
|
||||||
include(../libs/qt-breakpad/qtbreakpad.pri)
|
include(../libs/qt-breakpad/qtbreakpad.pri)
|
||||||
|
|
||||||
LIBS *= -l$$qtLibraryName(ExtensionSystem) -l$$qtLibraryName(Aggregation) -l$$qtLibraryName(Utils)
|
LIBS *= -l$$qtLibraryName(ExtensionSystem) -l$$qtLibraryName(Aggregation) -l$$qtLibraryName(Utils) -l$$qtLibraryName(QtcSsh)
|
||||||
|
|
||||||
win32 {
|
win32 {
|
||||||
# We need the version in two separate formats for the .rc file
|
# We need the version in two separate formats for the .rc file
|
||||||
|
@@ -46,6 +46,7 @@ QtcProduct {
|
|||||||
Depends { name: "app_version_header" }
|
Depends { name: "app_version_header" }
|
||||||
Depends { name: "Qt"; submodules: ["widgets", "network"] }
|
Depends { name: "Qt"; submodules: ["widgets", "network"] }
|
||||||
Depends { name: "Utils" }
|
Depends { name: "Utils" }
|
||||||
|
Depends { name: "QtcSsh" }
|
||||||
Depends { name: "ExtensionSystem" }
|
Depends { name: "ExtensionSystem" }
|
||||||
|
|
||||||
files: [
|
files: [
|
||||||
|
@@ -32,6 +32,8 @@
|
|||||||
#include <extensionsystem/pluginspec.h>
|
#include <extensionsystem/pluginspec.h>
|
||||||
#include <qtsingleapplication.h>
|
#include <qtsingleapplication.h>
|
||||||
|
|
||||||
|
#include <ssh/sshconnectionmanager.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
@@ -538,6 +540,7 @@ int main(int argc, char **argv)
|
|||||||
Utils::ProcessReaper processReaper;
|
Utils::ProcessReaper processReaper;
|
||||||
Utils::LauncherInterface::startLauncher();
|
Utils::LauncherInterface::startLauncher();
|
||||||
auto cleanup = qScopeGuard([] { Utils::LauncherInterface::stopLauncher(); });
|
auto cleanup = qScopeGuard([] { Utils::LauncherInterface::stopLauncher(); });
|
||||||
|
QSsh::SshConnectionManager sshConnectionManager;
|
||||||
|
|
||||||
const QStringList pluginArguments = app.arguments();
|
const QStringList pluginArguments = app.arguments();
|
||||||
|
|
||||||
|
@@ -113,7 +113,7 @@ SftpFileSystemModel::~SftpFileSystemModel()
|
|||||||
void SftpFileSystemModel::setSshConnection(const SshConnectionParameters &sshParams)
|
void SftpFileSystemModel::setSshConnection(const SshConnectionParameters &sshParams)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(!d->sshConnection, return);
|
QTC_ASSERT(!d->sshConnection, return);
|
||||||
d->sshConnection = QSsh::acquireConnection(sshParams);
|
d->sshConnection = SshConnectionManager::acquireConnection(sshParams);
|
||||||
connect(d->sshConnection, &SshConnection::errorOccurred,
|
connect(d->sshConnection, &SshConnection::errorOccurred,
|
||||||
this, &SftpFileSystemModel::handleSshConnectionFailure);
|
this, &SftpFileSystemModel::handleSshConnectionFailure);
|
||||||
if (d->sshConnection->state() == SshConnection::Connected) {
|
if (d->sshConnection->state() == SshConnection::Connected) {
|
||||||
@@ -268,7 +268,7 @@ void SftpFileSystemModel::shutDown()
|
|||||||
}
|
}
|
||||||
if (d->sshConnection) {
|
if (d->sshConnection) {
|
||||||
disconnect(d->sshConnection, nullptr, this, nullptr);
|
disconnect(d->sshConnection, nullptr, this, nullptr);
|
||||||
QSsh::releaseConnection(d->sshConnection);
|
SshConnectionManager::releaseConnection(d->sshConnection);
|
||||||
d->sshConnection = nullptr;
|
d->sshConnection = nullptr;
|
||||||
}
|
}
|
||||||
delete d->rootNode;
|
delete d->rootNode;
|
||||||
|
@@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
namespace QSsh {
|
namespace QSsh {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class UnacquiredConnection {
|
class UnacquiredConnection {
|
||||||
public:
|
public:
|
||||||
UnacquiredConnection(SshConnection *conn) : connection(conn), scheduledForRemoval(false) {}
|
UnacquiredConnection(SshConnection *conn) : connection(conn), scheduledForRemoval(false) {}
|
||||||
@@ -52,21 +53,25 @@ bool operator!=(const UnacquiredConnection &c1, const UnacquiredConnection &c2)
|
|||||||
return !(c1 == c2);
|
return !(c1 == c2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static class SshConnectionManager *s_instance = nullptr;
|
static class SshConnectionManagerPrivate *s_instance = nullptr;
|
||||||
|
|
||||||
class SshConnectionManager : public QObject
|
class SshConnectionManagerPrivate : public QObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SshConnectionManager(QObject *parent)
|
SshConnectionManagerPrivate()
|
||||||
: QObject(parent)
|
|
||||||
{
|
{
|
||||||
|
QTC_ASSERT(s_instance == nullptr, return);
|
||||||
|
s_instance = this;
|
||||||
|
|
||||||
connect(&m_removalTimer, &QTimer::timeout,
|
connect(&m_removalTimer, &QTimer::timeout,
|
||||||
this, &SshConnectionManager::removeInactiveConnections);
|
this, &SshConnectionManagerPrivate::removeInactiveConnections);
|
||||||
m_removalTimer.start(SshSettings::connectionSharingTimeout() * 1000 * 60 / 2);
|
m_removalTimer.start(SshSettings::connectionSharingTimeout() * 1000 * 60 / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
~SshConnectionManager()
|
~SshConnectionManagerPrivate() override
|
||||||
{
|
{
|
||||||
|
QTC_ASSERT(s_instance == this, return);
|
||||||
|
|
||||||
for (const UnacquiredConnection &connection : qAsConst(m_unacquiredConnections)) {
|
for (const UnacquiredConnection &connection : qAsConst(m_unacquiredConnections)) {
|
||||||
disconnect(connection.connection, nullptr, this, nullptr);
|
disconnect(connection.connection, nullptr, this, nullptr);
|
||||||
delete connection.connection;
|
delete connection.connection;
|
||||||
@@ -110,7 +115,7 @@ public:
|
|||||||
// create a new connection:
|
// create a new connection:
|
||||||
SshConnection * const connection = new SshConnection(sshParams);
|
SshConnection * const connection = new SshConnection(sshParams);
|
||||||
connect(connection, &SshConnection::disconnected,
|
connect(connection, &SshConnection::disconnected,
|
||||||
this, &SshConnectionManager::cleanup);
|
this, &SshConnectionManagerPrivate::cleanup);
|
||||||
if (SshSettings::connectionSharingEnabled())
|
if (SshSettings::connectionSharingEnabled())
|
||||||
m_acquiredConnections.append(connection);
|
m_acquiredConnections.append(connection);
|
||||||
|
|
||||||
@@ -203,29 +208,34 @@ private:
|
|||||||
QTimer m_removalTimer;
|
QTimer m_removalTimer;
|
||||||
};
|
};
|
||||||
|
|
||||||
static SshConnectionManager *instance()
|
|
||||||
{
|
|
||||||
QTC_CHECK(QThread::currentThread() == qApp->thread());
|
|
||||||
if (s_instance == nullptr)
|
|
||||||
s_instance = new SshConnectionManager(qApp); // Deleted together with application
|
|
||||||
return s_instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|
||||||
SshConnection *acquireConnection(const SshConnectionParameters &sshParams)
|
SshConnectionManager::SshConnectionManager()
|
||||||
|
: d(new Internal::SshConnectionManagerPrivate())
|
||||||
{
|
{
|
||||||
return Internal::instance()->acquireConnection(sshParams);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void releaseConnection(SshConnection *connection)
|
SshConnectionManager::~SshConnectionManager()
|
||||||
{
|
{
|
||||||
Internal::instance()->releaseConnection(connection);
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
void forceNewConnection(const SshConnectionParameters &sshParams)
|
SshConnection *SshConnectionManager::acquireConnection(const SshConnectionParameters &sshParams)
|
||||||
{
|
{
|
||||||
Internal::instance()->forceNewConnection(sshParams);
|
QTC_ASSERT(Internal::s_instance, return nullptr);
|
||||||
|
return Internal::s_instance->acquireConnection(sshParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SshConnectionManager::releaseConnection(SshConnection *connection)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(Internal::s_instance, return);
|
||||||
|
Internal::s_instance->releaseConnection(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SshConnectionManager::forceNewConnection(const SshConnectionParameters &sshParams)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(Internal::s_instance, return);
|
||||||
|
Internal::s_instance->forceNewConnection(sshParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace QSsh
|
} // namespace QSsh
|
||||||
|
@@ -32,10 +32,21 @@ namespace QSsh {
|
|||||||
class SshConnection;
|
class SshConnection;
|
||||||
class SshConnectionParameters;
|
class SshConnectionParameters;
|
||||||
|
|
||||||
QSSH_EXPORT SshConnection *acquireConnection(const SshConnectionParameters &sshParams);
|
namespace Internal { class SshConnectionManagerPrivate; }
|
||||||
QSSH_EXPORT void releaseConnection(SshConnection *connection);
|
|
||||||
|
|
||||||
|
class QSSH_EXPORT SshConnectionManager final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SshConnectionManager();
|
||||||
|
~SshConnectionManager();
|
||||||
|
|
||||||
|
static SshConnection *acquireConnection(const SshConnectionParameters &sshParams);
|
||||||
|
static void releaseConnection(SshConnection *connection);
|
||||||
// Make sure the next acquireConnection with the given parameters will return a new connection.
|
// Make sure the next acquireConnection with the given parameters will return a new connection.
|
||||||
QSSH_EXPORT void forceNewConnection(const SshConnectionParameters &sshParams);
|
static void forceNewConnection(const SshConnectionParameters &sshParams);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Internal::SshConnectionManagerPrivate *d;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace QSsh
|
} // namespace QSsh
|
||||||
|
@@ -100,7 +100,7 @@ void SshRemoteProcessRunner::runInternal(const QString &command,
|
|||||||
d->m_processErrorString.clear();
|
d->m_processErrorString.clear();
|
||||||
d->m_exitCode = -1;
|
d->m_exitCode = -1;
|
||||||
d->m_command = command;
|
d->m_command = command;
|
||||||
d->m_connection = QSsh::acquireConnection(sshParams);
|
d->m_connection = SshConnectionManager::acquireConnection(sshParams);
|
||||||
connect(d->m_connection, &SshConnection::errorOccurred,
|
connect(d->m_connection, &SshConnection::errorOccurred,
|
||||||
this, &SshRemoteProcessRunner::handleConnectionError);
|
this, &SshRemoteProcessRunner::handleConnectionError);
|
||||||
connect(d->m_connection, &SshConnection::disconnected,
|
connect(d->m_connection, &SshConnection::disconnected,
|
||||||
@@ -190,7 +190,7 @@ void SshRemoteProcessRunner::setState(int newState)
|
|||||||
}
|
}
|
||||||
if (d->m_connection) {
|
if (d->m_connection) {
|
||||||
disconnect(d->m_connection, nullptr, this, nullptr);
|
disconnect(d->m_connection, nullptr, this, nullptr);
|
||||||
QSsh::releaseConnection(d->m_connection);
|
SshConnectionManager::releaseConnection(d->m_connection);
|
||||||
d->m_connection = nullptr;
|
d->m_connection = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -96,7 +96,7 @@ void SshDeviceProcess::start(const Runnable &runnable)
|
|||||||
d->runnable = runnable;
|
d->runnable = runnable;
|
||||||
QSsh::SshConnectionParameters params = device()->sshParameters();
|
QSsh::SshConnectionParameters params = device()->sshParameters();
|
||||||
params.x11DisplayName = d->displayName();
|
params.x11DisplayName = d->displayName();
|
||||||
d->connection = QSsh::acquireConnection(params);
|
d->connection = QSsh::SshConnectionManager::acquireConnection(params);
|
||||||
connect(d->connection, &QSsh::SshConnection::errorOccurred,
|
connect(d->connection, &QSsh::SshConnection::errorOccurred,
|
||||||
this, &SshDeviceProcess::handleConnectionError);
|
this, &SshDeviceProcess::handleConnectionError);
|
||||||
connect(d->connection, &QSsh::SshConnection::disconnected,
|
connect(d->connection, &QSsh::SshConnection::disconnected,
|
||||||
@@ -364,7 +364,7 @@ void SshDeviceProcess::SshDeviceProcessPrivate::setState(SshDeviceProcess::SshDe
|
|||||||
process->disconnect(q);
|
process->disconnect(q);
|
||||||
if (connection) {
|
if (connection) {
|
||||||
connection->disconnect(q);
|
connection->disconnect(q);
|
||||||
QSsh::releaseConnection(connection);
|
QSsh::SshConnectionManager::releaseConnection(connection);
|
||||||
connection = nullptr;
|
connection = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -194,7 +194,7 @@ void AbstractRemoteLinuxDeployService::handleDeviceSetupDone(bool success)
|
|||||||
}
|
}
|
||||||
|
|
||||||
d->state = Connecting;
|
d->state = Connecting;
|
||||||
d->connection = QSsh::acquireConnection(deviceConfiguration()->sshParameters());
|
d->connection = SshConnectionManager::acquireConnection(deviceConfiguration()->sshParameters());
|
||||||
connect(d->connection, &SshConnection::errorOccurred,
|
connect(d->connection, &SshConnection::errorOccurred,
|
||||||
this, &AbstractRemoteLinuxDeployService::handleConnectionFailure);
|
this, &AbstractRemoteLinuxDeployService::handleConnectionFailure);
|
||||||
if (d->connection->state() == SshConnection::Connected) {
|
if (d->connection->state() == SshConnection::Connected) {
|
||||||
@@ -259,7 +259,7 @@ void AbstractRemoteLinuxDeployService::setFinished()
|
|||||||
d->state = Inactive;
|
d->state = Inactive;
|
||||||
if (d->connection) {
|
if (d->connection) {
|
||||||
disconnect(d->connection, nullptr, this, nullptr);
|
disconnect(d->connection, nullptr, this, nullptr);
|
||||||
QSsh::releaseConnection(d->connection);
|
SshConnectionManager::releaseConnection(d->connection);
|
||||||
d->connection = nullptr;
|
d->connection = nullptr;
|
||||||
}
|
}
|
||||||
d->stopRequested = false;
|
d->stopRequested = false;
|
||||||
|
@@ -72,7 +72,7 @@ GenericLinuxDeviceTester::GenericLinuxDeviceTester(QObject *parent)
|
|||||||
GenericLinuxDeviceTester::~GenericLinuxDeviceTester()
|
GenericLinuxDeviceTester::~GenericLinuxDeviceTester()
|
||||||
{
|
{
|
||||||
if (d->connection)
|
if (d->connection)
|
||||||
releaseConnection(d->connection);
|
SshConnectionManager::releaseConnection(d->connection);
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,8 +81,8 @@ void GenericLinuxDeviceTester::testDevice(const IDevice::Ptr &deviceConfiguratio
|
|||||||
QTC_ASSERT(d->state == Inactive, return);
|
QTC_ASSERT(d->state == Inactive, return);
|
||||||
|
|
||||||
d->deviceConfiguration = deviceConfiguration;
|
d->deviceConfiguration = deviceConfiguration;
|
||||||
forceNewConnection(deviceConfiguration->sshParameters());
|
SshConnectionManager::forceNewConnection(deviceConfiguration->sshParameters());
|
||||||
d->connection = acquireConnection(deviceConfiguration->sshParameters());
|
d->connection = SshConnectionManager::acquireConnection(deviceConfiguration->sshParameters());
|
||||||
connect(d->connection, &SshConnection::connected,
|
connect(d->connection, &SshConnection::connected,
|
||||||
this, &GenericLinuxDeviceTester::handleConnected);
|
this, &GenericLinuxDeviceTester::handleConnected);
|
||||||
connect(d->connection, &SshConnection::errorOccurred,
|
connect(d->connection, &SshConnection::errorOccurred,
|
||||||
@@ -275,7 +275,7 @@ void GenericLinuxDeviceTester::setFinished(TestResult result)
|
|||||||
}
|
}
|
||||||
if (d->connection) {
|
if (d->connection) {
|
||||||
disconnect(d->connection, nullptr, this, nullptr);
|
disconnect(d->connection, nullptr, this, nullptr);
|
||||||
releaseConnection(d->connection);
|
SshConnectionManager::releaseConnection(d->connection);
|
||||||
d->connection = nullptr;
|
d->connection = nullptr;
|
||||||
}
|
}
|
||||||
emit finished(result);
|
emit finished(result);
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
#include <ssh/sftpsession.h>
|
#include <ssh/sftpsession.h>
|
||||||
#include <ssh/sftptransfer.h>
|
#include <ssh/sftptransfer.h>
|
||||||
#include <ssh/sshconnection.h>
|
#include <ssh/sshconnection.h>
|
||||||
|
#include <ssh/sshconnectionmanager.h>
|
||||||
#include <ssh/sshremoteprocessrunner.h>
|
#include <ssh/sshremoteprocessrunner.h>
|
||||||
#include <ssh/sshsettings.h>
|
#include <ssh/sshsettings.h>
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
@@ -115,6 +116,8 @@ private slots:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool waitForConnection(SshConnection &connection);
|
bool waitForConnection(SshConnection &connection);
|
||||||
|
|
||||||
|
SshConnectionManager sshConnectionManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
void tst_Ssh::initTestCase()
|
void tst_Ssh::initTestCase()
|
||||||
|
Reference in New Issue
Block a user