SSH: Don't expose SshRemoteProcess object from SshRemoteProcessRunner.

It's part of the internal state.

Change-Id: I2670be2d55c791435bd286150f4b4097e8d92f6d
Reviewed-by: Tobias Hunger <tobias.hunger@nokia.com>
This commit is contained in:
Christian Kandeler
2011-11-30 14:39:17 +01:00
parent 5ff9d60433
commit 51511a3c59
13 changed files with 103 additions and 40 deletions

View File

@@ -62,6 +62,10 @@ public:
QByteArray m_command; QByteArray m_command;
Utils::SshError m_lastConnectionError; Utils::SshError m_lastConnectionError;
QString m_lastConnectionErrorString; QString m_lastConnectionErrorString;
SshRemoteProcess::ExitStatus m_exitStatus;
QByteArray m_exitSignal;
int m_exitCode;
QString m_processErrorString;
State m_state; State m_state;
}; };
@@ -84,6 +88,8 @@ SshRemoteProcessRunner::~SshRemoteProcessRunner()
void SshRemoteProcessRunner::run(const QByteArray &command, void SshRemoteProcessRunner::run(const QByteArray &command,
const SshConnectionParameters &sshParams) const SshConnectionParameters &sshParams)
{ {
QTC_ASSERT(d->m_state == Inactive, return);
d->m_runInTerminal = false; d->m_runInTerminal = false;
runInternal(command, sshParams); runInternal(command, sshParams);
} }
@@ -99,11 +105,13 @@ void SshRemoteProcessRunner::runInTerminal(const QByteArray &command,
void SshRemoteProcessRunner::runInternal(const QByteArray &command, void SshRemoteProcessRunner::runInternal(const QByteArray &command,
const SshConnectionParameters &sshParams) const SshConnectionParameters &sshParams)
{ {
setState(Inactive);
setState(Connecting); setState(Connecting);
d->m_lastConnectionError = SshNoError; d->m_lastConnectionError = SshNoError;
d->m_lastConnectionErrorString.clear(); d->m_lastConnectionErrorString.clear();
d->m_processErrorString.clear();
d->m_exitSignal.clear();
d->m_exitCode = -1;
d->m_command = command; d->m_command = command;
d->m_connection = SshConnectionManager::instance().acquireConnection(sshParams); d->m_connection = SshConnectionManager::instance().acquireConnection(sshParams);
connect(d->m_connection.data(), SIGNAL(error(Utils::SshError)), connect(d->m_connection.data(), SIGNAL(error(Utils::SshError)),
@@ -158,17 +166,23 @@ void SshRemoteProcessRunner::handleProcessStarted()
void SshRemoteProcessRunner::handleProcessFinished(int exitStatus) void SshRemoteProcessRunner::handleProcessFinished(int exitStatus)
{ {
switch (exitStatus) { d->m_exitStatus = static_cast<SshRemoteProcess::ExitStatus>(exitStatus);
switch (d->m_exitStatus) {
case SshRemoteProcess::FailedToStart: case SshRemoteProcess::FailedToStart:
QTC_ASSERT(d->m_state == Connected, return); QTC_ASSERT(d->m_state == Connected, return);
break; break;
case SshRemoteProcess::KilledBySignal: case SshRemoteProcess::KilledBySignal:
QTC_ASSERT(d->m_state == ProcessRunning, return);
d->m_exitSignal = d->m_process->exitSignal();
break;
case SshRemoteProcess::ExitedNormally: case SshRemoteProcess::ExitedNormally:
QTC_ASSERT(d->m_state == ProcessRunning, return); QTC_ASSERT(d->m_state == ProcessRunning, return);
d->m_exitCode = d->m_process->exitCode();
break; break;
default: default:
Q_ASSERT_X(false, Q_FUNC_INFO, "Impossible exit status."); Q_ASSERT_X(false, Q_FUNC_INFO, "Impossible exit status.");
} }
d->m_processErrorString = d->m_process->errorString();
setState(Inactive); setState(Inactive);
emit processClosed(exitStatus); emit processClosed(exitStatus);
} }
@@ -190,8 +204,11 @@ void SshRemoteProcessRunner::setState(int newState)
d->m_state = static_cast<State>(newState); d->m_state = static_cast<State>(newState);
if (d->m_state == Inactive) { if (d->m_state == Inactive) {
if (d->m_process) if (d->m_process) {
disconnect(d->m_process.data(), 0, this, 0); disconnect(d->m_process.data(), 0, this, 0);
d->m_process->close();
d->m_process.clear();
}
if (d->m_connection) { if (d->m_connection) {
disconnect(d->m_connection.data(), 0, this, 0); disconnect(d->m_connection.data(), 0, this, 0);
SshConnectionManager::instance().releaseConnection(d->m_connection); SshConnectionManager::instance().releaseConnection(d->m_connection);
@@ -202,9 +219,53 @@ void SshRemoteProcessRunner::setState(int newState)
QByteArray SshRemoteProcessRunner::command() const { return d->m_command; } QByteArray SshRemoteProcessRunner::command() const { return d->m_command; }
SshError SshRemoteProcessRunner::lastConnectionError() const { return d->m_lastConnectionError; } SshError SshRemoteProcessRunner::lastConnectionError() const { return d->m_lastConnectionError; }
SshRemoteProcess::Ptr SshRemoteProcessRunner::process() const { return d->m_process; }
QString SshRemoteProcessRunner::lastConnectionErrorString() const { QString SshRemoteProcessRunner::lastConnectionErrorString() const {
return d->m_lastConnectionErrorString; return d->m_lastConnectionErrorString;
} }
bool SshRemoteProcessRunner::isProcessRunning() const
{
return d->m_process && d->m_process->isRunning();
}
SshRemoteProcess::ExitStatus SshRemoteProcessRunner::processExitStatus() const
{
QTC_CHECK(!isProcessRunning());
return d->m_exitStatus;
}
QByteArray SshRemoteProcessRunner::processExitSignal() const
{
QTC_CHECK(processExitStatus() == SshRemoteProcess::KilledBySignal);
return d->m_exitSignal;
}
int SshRemoteProcessRunner::processExitCode() const
{
QTC_CHECK(processExitStatus() == SshRemoteProcess::ExitedNormally);
return d->m_exitCode;
}
QString SshRemoteProcessRunner::processErrorString() const
{
return d->m_processErrorString;
}
void SshRemoteProcessRunner::writeDataToProcess(const QByteArray &data)
{
QTC_ASSERT(isProcessRunning(), return);
d->m_process->write(data);
}
void SshRemoteProcessRunner::sendSignalToProcess(const QByteArray &signal)
{
QTC_ASSERT(isProcessRunning(), return);
d->m_process->sendSignal(signal);
}
void SshRemoteProcessRunner::cancel()
{
setState(Inactive);
}
} // namespace Utils } // namespace Utils

View File

@@ -57,7 +57,14 @@ public:
Utils::SshError lastConnectionError() const; Utils::SshError lastConnectionError() const;
QString lastConnectionErrorString() const; QString lastConnectionErrorString() const;
SshRemoteProcess::Ptr process() const; bool isProcessRunning() const;
void writeDataToProcess(const QByteArray &data);
void sendSignalToProcess(const QByteArray &signal); // No effect with OpenSSH server.
void cancel(); // Does not stop remote process, just frees SSH-related process resources.
SshRemoteProcess::ExitStatus processExitStatus() const;
QByteArray processExitSignal() const;
int processExitCode() const;
QString processErrorString() const;
private slots: private slots:
void handleConnected(); void handleConnected();

View File

@@ -127,8 +127,7 @@ qint64 SshIODevice::readData (char * data, qint64 maxSize)
void SshIODevice::processStarted() void SshIODevice::processStarted()
{ {
proc = runner->process(); runner->writeDataToProcess(startupbuffer);
proc->write(startupbuffer);
} }
void SshIODevice::outputAvailable(const QByteArray &output) void SshIODevice::outputAvailable(const QByteArray &output)
@@ -197,10 +196,10 @@ LldbEngineHost::~LldbEngineHost()
m_guestProcess->terminate(); m_guestProcess->terminate();
m_guestProcess->kill(); m_guestProcess->kill();
} }
if (m_ssh && m_ssh->process().data()) { if (m_ssh && m_ssh->isProcessRunning()) {
// TODO: openssh doesn't do that // TODO: openssh doesn't do that
m_ssh->process()->kill(); m_ssh->sendSignalToProcess(Utils::SshRemoteProcess::KillSignal);
} }
} }

View File

@@ -89,7 +89,7 @@ void MaddeDeviceTester::stopTest()
case QtTest: case QtTest:
case MadDeveloperTest: case MadDeveloperTest:
case QmlToolingTest: case QmlToolingTest:
m_processRunner->process()->close(); m_processRunner->cancel();
break; break;
} }
@@ -177,7 +177,7 @@ void MaddeDeviceTester::handleProcessFinished(int exitStatus)
void MaddeDeviceTester::handleQtTestFinished(int exitStatus) void MaddeDeviceTester::handleQtTestFinished(int exitStatus)
{ {
if (exitStatus != SshRemoteProcess::ExitedNormally if (exitStatus != SshRemoteProcess::ExitedNormally
|| m_processRunner->process()->exitCode() != 0) { || m_processRunner->processExitCode() != 0) {
if (!m_stderr.isEmpty()) { if (!m_stderr.isEmpty()) {
emit errorMessage(tr("Error checking for Qt libraries: %1\n") emit errorMessage(tr("Error checking for Qt libraries: %1\n")
.arg(QString::fromUtf8(m_stderr))); .arg(QString::fromUtf8(m_stderr)));
@@ -209,7 +209,7 @@ void MaddeDeviceTester::handleMadDeveloperTestFinished(int exitStatus)
emit errorMessage(tr("Error checking for connectivity tool.\n")); emit errorMessage(tr("Error checking for connectivity tool.\n"));
} }
m_result = TestFailure; m_result = TestFailure;
} else if (m_processRunner->process()->exitCode() != 0) { } else if (m_processRunner->processExitCode() != 0) {
QString message = tr("Connectivity tool not installed on device. " QString message = tr("Connectivity tool not installed on device. "
"Deployment currently not possible."); "Deployment currently not possible.");
if (m_deviceConfiguration->osType() == QLatin1String(HarmattanOsType)) { if (m_deviceConfiguration->osType() == QLatin1String(HarmattanOsType)) {
@@ -247,7 +247,7 @@ void MaddeDeviceTester::handleQmlToolingTestFinished(int exitStatus)
emit errorMessage(tr("Error checking for QML tooling support.\n")); emit errorMessage(tr("Error checking for QML tooling support.\n"));
} }
m_result = TestFailure; m_result = TestFailure;
} else if (m_processRunner->process()->exitCode() != 0) { } else if (m_processRunner->processExitCode() != 0) {
emit errorMessage(tr("Missing directory '%1'. You will not be able to do " emit errorMessage(tr("Missing directory '%1'. You will not be able to do "
"QML debugging on this device.\n").arg(QmlToolingDirectory)); "QML debugging on this device.\n").arg(QmlToolingDirectory));
m_result = TestFailure; m_result = TestFailure;

View File

@@ -419,11 +419,11 @@ void MaemoPublisherFremantleFree::handleUploadJobFinished(int exitStatus)
return); return);
if (m_state != Inactive && (exitStatus != SshRemoteProcess::ExitedNormally if (m_state != Inactive && (exitStatus != SshRemoteProcess::ExitedNormally
|| m_uploader->process()->exitCode() != 0)) { || m_uploader->processExitCode() != 0)) {
QString error; QString error;
if (exitStatus != SshRemoteProcess::ExitedNormally) { if (exitStatus != SshRemoteProcess::ExitedNormally) {
error = tr("Error uploading file: %1.") error = tr("Error uploading file: %1.")
.arg(m_uploader->process()->errorString()); .arg(m_uploader->processErrorString());
} else { } else {
error = tr("Error uploading file."); error = tr("Error uploading file.");
} }
@@ -447,7 +447,7 @@ void MaemoPublisherFremantleFree::prepareToSendFile()
emit progressReport(tr("Uploading file %1 ...") emit progressReport(tr("Uploading file %1 ...")
.arg(QDir::toNativeSeparators(nextFilePath))); .arg(QDir::toNativeSeparators(nextFilePath)));
QFileInfo info(nextFilePath); QFileInfo info(nextFilePath);
m_uploader->process()->write("C0644 " + QByteArray::number(info.size()) m_uploader->writeDataToProcess("C0644 " + QByteArray::number(info.size())
+ ' ' + info.fileName().toUtf8() + '\n'); + ' ' + info.fileName().toUtf8() + '\n');
} }
@@ -473,13 +473,13 @@ void MaemoPublisherFremantleFree::sendFile()
tr("Upload failed.")); tr("Upload failed."));
return; return;
} }
m_uploader->process()->write(data); m_uploader->writeDataToProcess(data);
bytesToSend -= data.size(); bytesToSend -= data.size();
QCoreApplication::processEvents(); QCoreApplication::processEvents();
if (m_state == Inactive) if (m_state == Inactive)
return; return;
} }
m_uploader->process()->write(QByteArray(1, '\0')); m_uploader->writeDataToProcess(QByteArray(1, '\0'));
} }
void MaemoPublisherFremantleFree::handleScpStdOut(const QByteArray &output) void MaemoPublisherFremantleFree::handleScpStdOut(const QByteArray &output)

View File

@@ -108,7 +108,7 @@ void MaemoRemoteCopyFacility::handleCopyFinished(int exitStatus)
return; return;
if (exitStatus != SshRemoteProcess::ExitedNormally if (exitStatus != SshRemoteProcess::ExitedNormally
|| m_copyRunner->process()->exitCode() != 0) { || m_copyRunner->processExitCode() != 0) {
setFinished(); setFinished();
emit finished(tr("Error: Copy command failed.")); emit finished(tr("Error: Copy command failed."));
} else { } else {

View File

@@ -115,7 +115,7 @@ void RemoteLinuxCustomCommandDeployService::stopDeployment()
QTC_ASSERT(d->state == Running, return); QTC_ASSERT(d->state == Running, return);
disconnect(d->runner, 0, this, 0); disconnect(d->runner, 0, this, 0);
d->runner->process()->close(); d->runner->cancel();
d->state = Inactive; d->state = Inactive;
handleDeploymentDone(); handleDeploymentDone();
} }
@@ -138,9 +138,9 @@ void RemoteLinuxCustomCommandDeployService::handleProcessClosed(int exitStatus)
emit errorMessage(tr("Remote process failed to start.")); emit errorMessage(tr("Remote process failed to start."));
} else if (exitStatus == SshRemoteProcess::KilledBySignal) { } else if (exitStatus == SshRemoteProcess::KilledBySignal) {
emit errorMessage(tr("Remote process was killed by a signal.")); emit errorMessage(tr("Remote process was killed by a signal."));
} else if (d->runner->process()->exitCode() != 0) { } else if (d->runner->processExitCode() != 0) {
emit errorMessage(tr("Remote process finished with exit code %1.") emit errorMessage(tr("Remote process finished with exit code %1.")
.arg(d->runner->process()->exitCode())); .arg(d->runner->processExitCode()));
} else { } else {
emit progressMessage(tr("Remote command finished successfully.")); emit progressMessage(tr("Remote command finished successfully."));
} }

View File

@@ -118,7 +118,7 @@ void RemoteLinuxEnvironmentReader::remoteProcessFinished(int exitCode)
} }
} else { } else {
QString errorMsg = tr("Error running remote process: %1") QString errorMsg = tr("Error running remote process: %1")
.arg(m_remoteProcessRunner->process()->errorString()); .arg(m_remoteProcessRunner->processErrorString());
if (!m_remoteErrorOutput.isEmpty()) { if (!m_remoteErrorOutput.isEmpty()) {
errorMsg += tr("\nRemote stderr was: '%1'") errorMsg += tr("\nRemote stderr was: '%1'")
.arg(QString::fromUtf8(m_remoteErrorOutput)); .arg(QString::fromUtf8(m_remoteErrorOutput));

View File

@@ -112,8 +112,7 @@ void AbstractRemoteLinuxPackageInstaller::handleInstallationFinished(int exitSta
if (!d->isRunning) if (!d->isRunning)
return; return;
if (exitStatus != SshRemoteProcess::ExitedNormally if (exitStatus != SshRemoteProcess::ExitedNormally || d->installer->processExitCode() != 0) {
|| d->installer->process()->exitCode() != 0) {
emit finished(tr("Installing package failed.")); emit finished(tr("Installing package failed."));
} else if (!errorString().isEmpty()) { } else if (!errorString().isEmpty()) {
emit finished(errorString()); emit finished(errorString());

View File

@@ -168,14 +168,14 @@ void AbstractRemoteLinuxProcessList::handleRemoteProcessFinished(int exitStatus)
switch (exitStatus) { switch (exitStatus) {
case SshRemoteProcess::FailedToStart: case SshRemoteProcess::FailedToStart:
d->errorMsg = tr("Error: Remote process failed to start: %1") d->errorMsg = tr("Error: Remote process failed to start: %1")
.arg(d->process.process()->errorString()); .arg(d->process.processErrorString());
break; break;
case SshRemoteProcess::KilledBySignal: case SshRemoteProcess::KilledBySignal:
d->errorMsg = tr("Error: Remote process crashed: %1") d->errorMsg = tr("Error: Remote process crashed: %1")
.arg(d->process.process()->errorString()); .arg(d->process.processErrorString());
break; break;
case SshRemoteProcess::ExitedNormally: case SshRemoteProcess::ExitedNormally:
if (d->process.process()->exitCode() == 0) { if (d->process.processExitCode() == 0) {
if (d->state == Listing) { if (d->state == Listing) {
d->remoteProcesses = buildProcessList(QString::fromUtf8(d->remoteStdout.data(), d->remoteProcesses = buildProcessList(QString::fromUtf8(d->remoteStdout.data(),
d->remoteStdout.count())); d->remoteStdout.count()));

View File

@@ -162,18 +162,18 @@ void RemoteLinuxUsedPortsGatherer::handleProcessClosed(int exitStatus)
switch (exitStatus) { switch (exitStatus) {
case SshRemoteProcess::FailedToStart: case SshRemoteProcess::FailedToStart:
errMsg = tr("Could not start remote process: %1") errMsg = tr("Could not start remote process: %1")
.arg(d->procRunner.process()->errorString()); .arg(d->procRunner.processErrorString());
break; break;
case SshRemoteProcess::KilledBySignal: case SshRemoteProcess::KilledBySignal:
errMsg = tr("Remote process crashed: %1") errMsg = tr("Remote process crashed: %1")
.arg(d->procRunner.process()->errorString()); .arg(d->procRunner.processErrorString());
break; break;
case SshRemoteProcess::ExitedNormally: case SshRemoteProcess::ExitedNormally:
if (d->procRunner.process()->exitCode() == 0) { if (d->procRunner.processExitCode() == 0) {
setupUsedPorts(); setupUsedPorts();
} else { } else {
errMsg = tr("Remote process failed; exit code was %1.") errMsg = tr("Remote process failed; exit code was %1.")
.arg(d->procRunner.process()->exitCode()); .arg(d->procRunner.processExitCode());
} }
break; break;
default: default:

View File

@@ -91,11 +91,8 @@ void SshKeyDeployer::handleKeyUploadFinished(int exitStatus)
|| exitStatus == SshRemoteProcess::KilledBySignal || exitStatus == SshRemoteProcess::KilledBySignal
|| exitStatus == SshRemoteProcess::ExitedNormally); || exitStatus == SshRemoteProcess::ExitedNormally);
if (!d->deployProcess.process()) const int exitCode = d->deployProcess.processExitCode();
return; const QString errorMsg = d->deployProcess.processErrorString();
const int exitCode = d->deployProcess.process()->exitCode();
const QString errorMsg = d->deployProcess.process()->errorString();
cleanup(); cleanup();
if (exitStatus == SshRemoteProcess::ExitedNormally && exitCode == 0) if (exitStatus == SshRemoteProcess::ExitedNormally && exitCode == 0)
emit finishedSuccessfully(); emit finishedSuccessfully();

View File

@@ -146,7 +146,7 @@ void RemoteProcessTest::handleProcessClosed(int exitStatus)
} }
switch (m_state) { switch (m_state) {
case TestingSuccess: { case TestingSuccess: {
const int exitCode = m_remoteRunner->process()->exitCode(); const int exitCode = m_remoteRunner->processExitCode();
if (exitCode != 0) { if (exitCode != 0) {
std::cerr << "Error: exit code is " << exitCode std::cerr << "Error: exit code is " << exitCode
<< ", expected zero." << std::endl; << ", expected zero." << std::endl;
@@ -168,7 +168,7 @@ void RemoteProcessTest::handleProcessClosed(int exitStatus)
break; break;
} }
case TestingFailure: { case TestingFailure: {
const int exitCode = m_remoteRunner->process()->exitCode(); const int exitCode = m_remoteRunner->processExitCode();
if (exitCode == 0) { if (exitCode == 0) {
std::cerr << "Error: exit code is zero, expected non-zero." std::cerr << "Error: exit code is zero, expected non-zero."
<< std::endl; << std::endl;
@@ -194,7 +194,7 @@ void RemoteProcessTest::handleProcessClosed(int exitStatus)
qApp->quit(); qApp->quit();
break; break;
case TestingTerminal: { case TestingTerminal: {
const int exitCode = m_remoteRunner->process()->exitCode(); const int exitCode = m_remoteRunner->processExitCode();
if (exitCode != 0) { if (exitCode != 0) {
std::cerr << "Error: exit code is " << exitCode std::cerr << "Error: exit code is " << exitCode
<< ", expected zero." << std::endl; << ", expected zero." << std::endl;