QtcProcess: Introduce done() signal

Introduce QtcProcess::done() signal. It's similar to
QtcProcess::finished() signal, but also emitted when
process failed to start (so after QProcess::FailedToStart
error occurred).

SshRemoteProcess::finished() signal was already behaving
like this. So, we remove special handling of
FailedToStart error in this class and connect all clients
of SshRemoteProcess to done() signal, instead of finished().

Task-number: QTCREATORBUG-27232
Change-Id: If4240e2172f3f706e812bca669a1d5b24bdc3285
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Jarek Kobus
2022-04-04 13:17:36 +02:00
parent d950eb498f
commit ab11c4373b
11 changed files with 55 additions and 52 deletions

View File

@@ -62,14 +62,7 @@ void SshRemoteProcess::emitFinished()
{ {
if (exitStatus() == QProcess::CrashExit) if (exitStatus() == QProcess::CrashExit)
m_errorString = tr("The ssh process crashed: %1").arg(errorString()); m_errorString = tr("The ssh process crashed: %1").arg(errorString());
emit finished(); QtcProcess::emitFinished();
}
void SshRemoteProcess::emitErrorOccurred(QProcess::ProcessError error)
{
if (error == QProcess::FailedToStart)
emit finished();
emit errorOccurred(error);
} }
void SshRemoteProcess::start() void SshRemoteProcess::start()

View File

@@ -50,7 +50,6 @@ public:
protected: protected:
void emitFinished() override; void emitFinished() override;
void emitErrorOccurred(QProcess::ProcessError error) override;
private: private:
QString m_remoteCommand; QString m_remoteCommand;

View File

@@ -36,6 +36,8 @@
running a remote process over an SSH connection. running a remote process over an SSH connection.
*/ */
using namespace Utils;
namespace QSsh { namespace QSsh {
namespace Internal { namespace Internal {
namespace { namespace {
@@ -109,13 +111,13 @@ void SshRemoteProcessRunner::handleConnected()
setState(Connected); setState(Connected);
d->m_process = d->m_connection->createRemoteProcess(d->m_command); d->m_process = d->m_connection->createRemoteProcess(d->m_command);
connect(d->m_process.get(), &SshRemoteProcess::started, connect(d->m_process.get(), &QtcProcess::started,
this, &SshRemoteProcessRunner::handleProcessStarted); this, &SshRemoteProcessRunner::handleProcessStarted);
connect(d->m_process.get(), &SshRemoteProcess::finished, connect(d->m_process.get(), &QtcProcess::done,
this, &SshRemoteProcessRunner::handleProcessFinished); this, &SshRemoteProcessRunner::handleProcessFinished);
connect(d->m_process.get(), &SshRemoteProcess::readyReadStandardOutput, connect(d->m_process.get(), &QtcProcess::readyReadStandardOutput,
this, &SshRemoteProcessRunner::readyReadStandardOutput); this, &SshRemoteProcessRunner::readyReadStandardOutput);
connect(d->m_process.get(), &SshRemoteProcess::readyReadStandardError, connect(d->m_process.get(), &QtcProcess::readyReadStandardError,
this, &SshRemoteProcessRunner::readyReadStandardError); this, &SshRemoteProcessRunner::readyReadStandardError);
d->m_process->start(); d->m_process->start();
} }

View File

@@ -590,6 +590,8 @@ public:
void handleError(QProcess::ProcessError error); void handleError(QProcess::ProcessError error);
void clearForRun(); void clearForRun();
void emitErrorOccurred(QProcess::ProcessError error);
ProcessResult interpretExitCode(int exitCode); ProcessResult interpretExitCode(int exitCode);
QTextCodec *m_codec = QTextCodec::codecForLocale(); QTextCodec *m_codec = QTextCodec::codecForLocale();
@@ -701,11 +703,7 @@ void QtcProcess::emitStarted()
void QtcProcess::emitFinished() void QtcProcess::emitFinished()
{ {
emit finished(); emit finished();
} emit done();
void QtcProcess::emitErrorOccurred(QProcess::ProcessError error)
{
emit errorOccurred(error);
} }
void QtcProcess::setProcessInterface(ProcessInterface *interface) void QtcProcess::setProcessInterface(ProcessInterface *interface)
@@ -1647,7 +1645,14 @@ void QtcProcessPrivate::handleError(QProcess::ProcessError error)
if (m_eventLoop) if (m_eventLoop)
m_eventLoop->quit(); m_eventLoop->quit();
q->emitErrorOccurred(error); emitErrorOccurred(error);
}
void QtcProcessPrivate::emitErrorOccurred(QProcess::ProcessError error)
{
emit q->errorOccurred(error);
if (error == QProcess::FailedToStart)
emit q->done();
} }
} // namespace Utils } // namespace Utils

View File

@@ -189,6 +189,8 @@ public:
signals: signals:
void started(); void started();
void finished(); void finished();
void done(); // The same as finished() with the addition it's being also emitted after
// FailedToStart error occurred.
void errorOccurred(QProcess::ProcessError error); void errorOccurred(QProcess::ProcessError error);
void readyReadStandardOutput(); void readyReadStandardOutput();
void readyReadStandardError(); void readyReadStandardError();
@@ -197,7 +199,6 @@ protected:
// TODO: remove these methods on QtcProcess de-virtualization // TODO: remove these methods on QtcProcess de-virtualization
virtual void emitStarted(); virtual void emitStarted();
virtual void emitFinished(); virtual void emitFinished();
virtual void emitErrorOccurred(QProcess::ProcessError error);
private: private:
void setProcessInterface(ProcessInterface *interface); void setProcessInterface(ProcessInterface *interface);

View File

@@ -197,14 +197,14 @@ void SshDeviceProcess::handleConnected()
setCommand(d->remoteProcess->fullLocalCommandLine(true)); setCommand(d->remoteProcess->fullLocalCommandLine(true));
QtcProcess::start(); QtcProcess::start();
} else { } else {
connect(d->remoteProcess.get(), &QSsh::SshRemoteProcess::started, connect(d->remoteProcess.get(), &QtcProcess::started,
this, &SshDeviceProcess::handleProcessStarted); this, &SshDeviceProcess::handleProcessStarted);
connect(d->remoteProcess.get(), &QSsh::SshRemoteProcess::finished, this, [this] { connect(d->remoteProcess.get(), &QtcProcess::done, this, [this] {
handleProcessFinished(d->remoteProcess->errorString()); handleProcessFinished(d->remoteProcess->errorString());
}); });
connect(d->remoteProcess.get(), &QSsh::SshRemoteProcess::readyReadStandardOutput, connect(d->remoteProcess.get(), &QtcProcess::readyReadStandardOutput,
this, &QtcProcess::readyReadStandardOutput); this, &QtcProcess::readyReadStandardOutput);
connect(d->remoteProcess.get(), &QSsh::SshRemoteProcess::readyReadStandardError, connect(d->remoteProcess.get(), &QtcProcess::readyReadStandardError,
this, &QtcProcess::readyReadStandardError); this, &QtcProcess::readyReadStandardError);
d->remoteProcess->start(); d->remoteProcess->start();
} }

View File

@@ -200,7 +200,7 @@ void GenericDirectUploadService::runStat(const DeployableFile &file)
const QString statCmd = "stat -t " + Utils::ProcessArgs::quoteArgUnix(file.remoteFilePath()); const QString statCmd = "stat -t " + Utils::ProcessArgs::quoteArgUnix(file.remoteFilePath());
SshRemoteProcess * const statProc = connection()->createRemoteProcess(statCmd).release(); SshRemoteProcess * const statProc = connection()->createRemoteProcess(statCmd).release();
statProc->setParent(this); statProc->setParent(this);
connect(statProc, &SshRemoteProcess::finished, this, [this, statProc, state = d->state] { connect(statProc, &QtcProcess::done, this, [this, statProc, state = d->state] {
QTC_ASSERT(d->state == state, return); QTC_ASSERT(d->state == state, return);
const DeployableFile file = d->getFileForProcess(statProc); const DeployableFile file = d->getFileForProcess(statProc);
QTC_ASSERT(file.isValid(), return); QTC_ASSERT(file.isValid(), return);
@@ -341,7 +341,7 @@ void GenericDirectUploadService::chmod()
SshRemoteProcess * const chmodProc SshRemoteProcess * const chmodProc
= connection()->createRemoteProcess(command).release(); = connection()->createRemoteProcess(command).release();
chmodProc->setParent(this); chmodProc->setParent(this);
connect(chmodProc, &SshRemoteProcess::finished, this, [this, chmodProc, state = d->state] { connect(chmodProc, &QtcProcess::done, this, [this, chmodProc, state = d->state] {
QTC_ASSERT(state == d->state, return); QTC_ASSERT(state == d->state, return);
const DeployableFile file = d->getFileForProcess(chmodProc); const DeployableFile file = d->getFileForProcess(chmodProc);
QTC_ASSERT(file.isValid(), return); QTC_ASSERT(file.isValid(), return);

View File

@@ -38,6 +38,7 @@
using namespace ProjectExplorer; using namespace ProjectExplorer;
using namespace QSsh; using namespace QSsh;
using namespace Utils;
namespace RemoteLinux { namespace RemoteLinux {
namespace Internal { namespace Internal {
@@ -55,7 +56,7 @@ public:
SshRemoteProcessPtr process; SshRemoteProcessPtr process;
DeviceUsedPortsGatherer portsGatherer; DeviceUsedPortsGatherer portsGatherer;
SftpTransferPtr sftpTransfer; SftpTransferPtr sftpTransfer;
Utils::QtcProcess rsyncProcess; QtcProcess rsyncProcess;
State state = Inactive; State state = Inactive;
bool sftpWorks = false; bool sftpWorks = false;
}; };
@@ -126,7 +127,7 @@ void GenericLinuxDeviceTester::handleConnected()
QTC_ASSERT(d->state == Connecting, return); QTC_ASSERT(d->state == Connecting, return);
d->process = d->connection->createRemoteProcess("uname -rsm"); d->process = d->connection->createRemoteProcess("uname -rsm");
connect(d->process.get(), &SshRemoteProcess::finished, connect(d->process.get(), &QtcProcess::done,
this, &GenericLinuxDeviceTester::handleProcessFinished); this, &GenericLinuxDeviceTester::handleProcessFinished);
emit progressMessage(tr("Checking kernel version...")); emit progressMessage(tr("Checking kernel version..."));
@@ -183,7 +184,7 @@ void GenericLinuxDeviceTester::handlePortListReady()
emit progressMessage(tr("All specified ports are available.") + QLatin1Char('\n')); emit progressMessage(tr("All specified ports are available.") + QLatin1Char('\n'));
} else { } else {
QString portList; QString portList;
foreach (const Utils::Port port, d->portsGatherer.usedPorts()) foreach (const Port port, d->portsGatherer.usedPorts())
portList += QString::number(port.number()) + QLatin1String(", "); portList += QString::number(port.number()) + QLatin1String(", ");
portList.remove(portList.count() - 2, 2); portList.remove(portList.count() - 2, 2);
emit errorMessage(tr("The following specified ports are currently in use: %1") emit errorMessage(tr("The following specified ports are currently in use: %1")
@@ -221,18 +222,18 @@ void GenericLinuxDeviceTester::handleSftpFinished(const QString &error)
void GenericLinuxDeviceTester::testRsync() void GenericLinuxDeviceTester::testRsync()
{ {
emit progressMessage(tr("Checking whether rsync works...")); emit progressMessage(tr("Checking whether rsync works..."));
connect(&d->rsyncProcess, &Utils::QtcProcess::errorOccurred, [this] { connect(&d->rsyncProcess, &QtcProcess::errorOccurred, [this] {
if (d->rsyncProcess.error() == QProcess::FailedToStart) if (d->rsyncProcess.error() == QProcess::FailedToStart)
handleRsyncFinished(); handleRsyncFinished();
}); });
connect(&d->rsyncProcess, &Utils::QtcProcess::finished, this, [this] { connect(&d->rsyncProcess, &QtcProcess::finished, this, [this] {
handleRsyncFinished(); handleRsyncFinished();
}); });
const RsyncCommandLine cmdLine = RsyncDeployStep::rsyncCommand(*d->connection, const RsyncCommandLine cmdLine = RsyncDeployStep::rsyncCommand(*d->connection,
RsyncDeployStep::defaultFlags()); RsyncDeployStep::defaultFlags());
const QStringList args = QStringList(cmdLine.options) const QStringList args = QStringList(cmdLine.options)
<< "-n" << "--exclude=*" << (cmdLine.remoteHostSpec + ":/tmp"); << "-n" << "--exclude=*" << (cmdLine.remoteHostSpec + ":/tmp");
d->rsyncProcess.setCommand(Utils::CommandLine("rsync", args)); d->rsyncProcess.setCommand(CommandLine("rsync", args));
d->rsyncProcess.start(); d->rsyncProcess.start();
} }

View File

@@ -103,7 +103,7 @@ void RsyncDeployService::createRemoteDirectories()
remoteDirs.removeDuplicates(); remoteDirs.removeDuplicates();
m_mkdir = connection()->createRemoteProcess("mkdir -p " + m_mkdir = connection()->createRemoteProcess("mkdir -p " +
ProcessArgs::createUnixArgs(remoteDirs).toString()); ProcessArgs::createUnixArgs(remoteDirs).toString());
connect(m_mkdir.get(), &SshRemoteProcess::finished, this, [this] { connect(m_mkdir.get(), &QtcProcess::done, this, [this] {
QString userError; QString userError;
const QString error = m_mkdir->errorString(); const QString error = m_mkdir->errorString();
if (!error.isEmpty()) if (!error.isEmpty())

View File

@@ -48,6 +48,7 @@
#include <cstdlib> #include <cstdlib>
using namespace QSsh; using namespace QSsh;
using namespace Utils;
class tst_Ssh : public QObject class tst_Ssh : public QObject
{ {
@@ -76,10 +77,10 @@ void tst_Ssh::initTestCase()
if (!SshTest::checkParameters(params)) if (!SshTest::checkParameters(params))
SshTest::printSetupHelp(); SshTest::printSetupHelp();
Utils::LauncherInterface::setPathToLauncher(qApp->applicationDirPath() + '/' LauncherInterface::setPathToLauncher(qApp->applicationDirPath() + '/'
+ QLatin1String(TEST_RELATIVE_LIBEXEC_PATH)); + QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
Utils::TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath() TemporaryDirectory::setMasterTemporaryDirectory(QDir::tempPath()
+ "/qtc-ssh-autotest-XXXXXX"); + "/qtc-ssh-autotest-XXXXXX");
} }
void tst_Ssh::errorHandling_data() void tst_Ssh::errorHandling_data()
@@ -118,7 +119,7 @@ void tst_Ssh::errorHandling()
params.setUserName(user); params.setUserName(user);
params.timeout = 3; params.timeout = 3;
params.authenticationType = authType; params.authenticationType = authType;
params.privateKeyFile = Utils::FilePath::fromString(keyFile); params.privateKeyFile = FilePath::fromString(keyFile);
SshConnection connection(params); SshConnection connection(params);
QEventLoop loop; QEventLoop loop;
bool disconnected = false; bool disconnected = false;
@@ -240,12 +241,12 @@ void tst_Ssh::remoteProcessChannels()
SshRemoteProcessPtr echoProcess SshRemoteProcessPtr echoProcess
= connection.createRemoteProcess("printf " + QString::fromUtf8(testString) + " >&2"); = connection.createRemoteProcess("printf " + QString::fromUtf8(testString) + " >&2");
QEventLoop loop; QEventLoop loop;
connect(echoProcess.get(), &SshRemoteProcess::finished, &loop, &QEventLoop::quit); connect(echoProcess.get(), &QtcProcess::done, &loop, &QEventLoop::quit);
connect(echoProcess.get(), &Utils::QtcProcess::readyReadStandardError, connect(echoProcess.get(), &QtcProcess::readyReadStandardError,
[&remoteData, p = echoProcess.get()] { remoteData += p->readAllStandardError(); }); [&remoteData, p = echoProcess.get()] { remoteData += p->readAllStandardError(); });
connect(echoProcess.get(), &SshRemoteProcess::readyReadStandardOutput, connect(echoProcess.get(), &QtcProcess::readyReadStandardOutput,
[&remoteStdout, p = echoProcess.get()] { remoteStdout += p->readAllStandardOutput(); }); [&remoteStdout, p = echoProcess.get()] { remoteStdout += p->readAllStandardOutput(); });
connect(echoProcess.get(), &SshRemoteProcess::readyReadStandardError, connect(echoProcess.get(), &QtcProcess::readyReadStandardError,
[&remoteStderr] { remoteStderr = testString; }); [&remoteStderr] { remoteStderr = testString; });
echoProcess->start(); echoProcess->start();
QTimer timer; QTimer timer;
@@ -273,10 +274,10 @@ void tst_Ssh::remoteProcessInput()
QVERIFY(waitForConnection(connection)); QVERIFY(waitForConnection(connection));
SshRemoteProcessPtr catProcess = connection.createRemoteProcess("/bin/cat"); SshRemoteProcessPtr catProcess = connection.createRemoteProcess("/bin/cat");
catProcess->setProcessMode(Utils::ProcessMode::Writer); catProcess->setProcessMode(ProcessMode::Writer);
QEventLoop loop; QEventLoop loop;
connect(catProcess.get(), &SshRemoteProcess::started, &loop, &QEventLoop::quit); connect(catProcess.get(), &QtcProcess::started, &loop, &QEventLoop::quit);
connect(catProcess.get(), &SshRemoteProcess::finished, &loop, &QEventLoop::quit); connect(catProcess.get(), &QtcProcess::done, &loop, &QEventLoop::quit);
QTimer timer; QTimer timer;
QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit); QObject::connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
timer.setSingleShot(true); timer.setSingleShot(true);
@@ -289,7 +290,7 @@ void tst_Ssh::remoteProcessInput()
QVERIFY(catProcess->isRunning()); QVERIFY(catProcess->isRunning());
static QString testString = "x\r\n"; static QString testString = "x\r\n";
connect(catProcess.get(), &Utils::QtcProcess::readyReadStandardOutput, &loop, &QEventLoop::quit); connect(catProcess.get(), &QtcProcess::readyReadStandardOutput, &loop, &QEventLoop::quit);
catProcess->write(testString.toUtf8()); catProcess->write(testString.toUtf8());
timer.start(); timer.start();
@@ -460,7 +461,7 @@ void tst_Ssh::sftp()
QVERIFY(success); QVERIFY(success);
// The same again, with a non-interactive download. // The same again, with a non-interactive download.
FilesToTransfer filesToDownload = Utils::transform(filesToUpload, [&](const FileToTransfer &fileToUpload) { const FilesToTransfer filesToDownload = transform(filesToUpload, [&](const FileToTransfer &fileToUpload) {
return FileToTransfer(fileToUpload.targetFile, return FileToTransfer(fileToUpload.targetFile,
getDownloadFilePath(dir2ForFilesToDownload, getDownloadFilePath(dir2ForFilesToDownload,
QFileInfo(fileToUpload.sourceFile).fileName())); QFileInfo(fileToUpload.sourceFile).fileName()));
@@ -574,7 +575,7 @@ void tst_Ssh::sftp()
void tst_Ssh::cleanupTestCase() void tst_Ssh::cleanupTestCase()
{ {
Utils::Singleton::deleteAll(); Singleton::deleteAll();
} }
bool tst_Ssh::waitForConnection(SshConnection &connection) bool tst_Ssh::waitForConnection(SshConnection &connection)

View File

@@ -35,6 +35,7 @@
#include <iostream> #include <iostream>
using namespace QSsh; using namespace QSsh;
using namespace Utils;
Shell::Shell(const SshConnectionParameters &parameters, QObject *parent) Shell::Shell(const SshConnectionParameters &parameters, QObject *parent)
: QObject(parent), : QObject(parent),
@@ -70,12 +71,12 @@ void Shell::handleConnectionError()
void Shell::handleConnected() void Shell::handleConnected()
{ {
m_shell = m_connection->createRemoteShell(); m_shell = m_connection->createRemoteShell();
connect(m_shell.get(), &SshRemoteProcess::started, this, &Shell::handleShellStarted); connect(m_shell.get(), &QtcProcess::started, this, &Shell::handleShellStarted);
connect(m_shell.get(), &SshRemoteProcess::readyReadStandardOutput, connect(m_shell.get(), &QtcProcess::readyReadStandardOutput,
this, &Shell::handleRemoteStdout); this, &Shell::handleRemoteStdout);
connect(m_shell.get(), &SshRemoteProcess::readyReadStandardError, connect(m_shell.get(), &QtcProcess::readyReadStandardError,
this, &Shell::handleRemoteStderr); this, &Shell::handleRemoteStderr);
connect(m_shell.get(), &SshRemoteProcess::finished, this, &Shell::handleChannelClosed); connect(m_shell.get(), &QtcProcess::done, this, &Shell::handleChannelClosed);
m_shell->start(); m_shell->start();
} }