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:
Jarek Kobus
2021-09-09 15:29:28 +02:00
parent 2bdbaaa2fd
commit 33f1a96005
12 changed files with 67 additions and 39 deletions

View File

@@ -113,7 +113,7 @@ SftpFileSystemModel::~SftpFileSystemModel()
void SftpFileSystemModel::setSshConnection(const SshConnectionParameters &sshParams)
{
QTC_ASSERT(!d->sshConnection, return);
d->sshConnection = QSsh::acquireConnection(sshParams);
d->sshConnection = SshConnectionManager::acquireConnection(sshParams);
connect(d->sshConnection, &SshConnection::errorOccurred,
this, &SftpFileSystemModel::handleSshConnectionFailure);
if (d->sshConnection->state() == SshConnection::Connected) {
@@ -268,7 +268,7 @@ void SftpFileSystemModel::shutDown()
}
if (d->sshConnection) {
disconnect(d->sshConnection, nullptr, this, nullptr);
QSsh::releaseConnection(d->sshConnection);
SshConnectionManager::releaseConnection(d->sshConnection);
d->sshConnection = nullptr;
}
delete d->rootNode;

View File

@@ -38,6 +38,7 @@
namespace QSsh {
namespace Internal {
class UnacquiredConnection {
public:
UnacquiredConnection(SshConnection *conn) : connection(conn), scheduledForRemoval(false) {}
@@ -52,21 +53,25 @@ bool operator!=(const UnacquiredConnection &c1, const UnacquiredConnection &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:
SshConnectionManager(QObject *parent)
: QObject(parent)
SshConnectionManagerPrivate()
{
QTC_ASSERT(s_instance == nullptr, return);
s_instance = this;
connect(&m_removalTimer, &QTimer::timeout,
this, &SshConnectionManager::removeInactiveConnections);
this, &SshConnectionManagerPrivate::removeInactiveConnections);
m_removalTimer.start(SshSettings::connectionSharingTimeout() * 1000 * 60 / 2);
}
~SshConnectionManager()
~SshConnectionManagerPrivate() override
{
QTC_ASSERT(s_instance == this, return);
for (const UnacquiredConnection &connection : qAsConst(m_unacquiredConnections)) {
disconnect(connection.connection, nullptr, this, nullptr);
delete connection.connection;
@@ -110,7 +115,7 @@ public:
// create a new connection:
SshConnection * const connection = new SshConnection(sshParams);
connect(connection, &SshConnection::disconnected,
this, &SshConnectionManager::cleanup);
this, &SshConnectionManagerPrivate::cleanup);
if (SshSettings::connectionSharingEnabled())
m_acquiredConnections.append(connection);
@@ -203,29 +208,34 @@ private:
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
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

View File

@@ -32,10 +32,21 @@ namespace QSsh {
class SshConnection;
class SshConnectionParameters;
QSSH_EXPORT SshConnection *acquireConnection(const SshConnectionParameters &sshParams);
QSSH_EXPORT void releaseConnection(SshConnection *connection);
namespace Internal { class SshConnectionManagerPrivate; }
// Make sure the next acquireConnection with the given parameters will return a new connection.
QSSH_EXPORT void forceNewConnection(const SshConnectionParameters &sshParams);
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.
static void forceNewConnection(const SshConnectionParameters &sshParams);
private:
Internal::SshConnectionManagerPrivate *d;
};
} // namespace QSsh

View File

@@ -100,7 +100,7 @@ void SshRemoteProcessRunner::runInternal(const QString &command,
d->m_processErrorString.clear();
d->m_exitCode = -1;
d->m_command = command;
d->m_connection = QSsh::acquireConnection(sshParams);
d->m_connection = SshConnectionManager::acquireConnection(sshParams);
connect(d->m_connection, &SshConnection::errorOccurred,
this, &SshRemoteProcessRunner::handleConnectionError);
connect(d->m_connection, &SshConnection::disconnected,
@@ -190,7 +190,7 @@ void SshRemoteProcessRunner::setState(int newState)
}
if (d->m_connection) {
disconnect(d->m_connection, nullptr, this, nullptr);
QSsh::releaseConnection(d->m_connection);
SshConnectionManager::releaseConnection(d->m_connection);
d->m_connection = nullptr;
}
}