Maemo: Fix UTFS server readiness detection.

This commit is contained in:
Christian Kandeler
2010-08-17 14:49:51 +02:00
parent cd57457a16
commit d1f0c171e2
4 changed files with 148 additions and 30 deletions

View File

@@ -557,6 +557,7 @@ void MaemoDeployStep::handleMounted()
void MaemoDeployStep::handleUnmounted() void MaemoDeployStep::handleUnmounted()
{ {
m_mounter->resetMountSpecifications();
if (m_stopped) { if (m_stopped) {
m_canStart = true; m_canStart = true;
return; return;
@@ -574,7 +575,7 @@ void MaemoDeployStep::handleUnmounted()
} else { } else {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
bool drivesToMount[26]; bool drivesToMount[26];
for (int i = 0; i < sizeof drivesToMount / drivesToMount[0]; ++i) for (int i = 0; i < sizeof drivesToMount / sizeof drivesToMount[0]; ++i)
drivesToMount[i] = false; drivesToMount[i] = false;
for (int i = 0; i < m_filesToCopy.count(); ++i) { for (int i = 0; i < m_filesToCopy.count(); ++i) {
const QString localDir = QFileInfo(m_filesToCopy.at(i).localFilePath) const QString localDir = QFileInfo(m_filesToCopy.at(i).localFilePath)

View File

@@ -36,7 +36,7 @@
#include <coreplugin/ssh/sshconnection.h> #include <coreplugin/ssh/sshconnection.h>
#include <coreplugin/ssh/sshremoteprocess.h> #include <coreplugin/ssh/sshremoteprocess.h>
#include <QtCore/QProcess> #include <QtCore/QTimer>
using namespace Core; using namespace Core;
@@ -45,12 +45,19 @@ namespace Internal {
MaemoRemoteMounter::MaemoRemoteMounter(QObject *parent, MaemoRemoteMounter::MaemoRemoteMounter(QObject *parent,
const MaemoToolChain *toolchain) const MaemoToolChain *toolchain)
: QObject(parent), m_toolChain(toolchain), m_uploadJobId(SftpInvalidJob), : QObject(parent), m_toolChain(toolchain),
m_utfsServerTimer(new QTimer(this)), m_uploadJobId(SftpInvalidJob),
m_stop(false) m_stop(false)
{ {
m_utfsServerTimer->setSingleShot(true);
connect(m_utfsServerTimer, SIGNAL(timeout()), this,
SLOT(handleUtfsServerTimeout()));
} }
MaemoRemoteMounter::~MaemoRemoteMounter() {} MaemoRemoteMounter::~MaemoRemoteMounter()
{
killAllUtfsServers();
}
void MaemoRemoteMounter::setConnection(const Core::SshConnection::Ptr &connection) void MaemoRemoteMounter::setConnection(const Core::SshConnection::Ptr &connection)
{ {
@@ -72,7 +79,8 @@ bool MaemoRemoteMounter::addMountSpecification(const MaemoMountSpecification &mo
void MaemoRemoteMounter::mount() void MaemoRemoteMounter::mount()
{ {
m_stop = false; m_stop = false;
Q_ASSERT(m_utfsServers.isEmpty()); Q_ASSERT(m_startedUtfsServers.isEmpty());
Q_ASSERT(m_readyUtfsServers.isEmpty());
if (m_mountSpecs.isEmpty()) if (m_mountSpecs.isEmpty())
emit mounted(); emit mounted();
@@ -126,13 +134,7 @@ void MaemoRemoteMounter::handleUnmountProcessFinished(int exitStatus)
"Impossible SshRemoteProcess exit status."); "Impossible SshRemoteProcess exit status.");
} }
foreach (const ProcPtr &utfsServer, m_utfsServers) { killAllUtfsServers();
utfsServer->terminate();
utfsServer->waitForFinished(1000);
utfsServer->kill();
}
m_mountSpecs.clear();
m_utfsServers.clear();
if (errorMsg.isEmpty()) { if (errorMsg.isEmpty()) {
emit reportProgress(tr("Finished unmounting.")); emit reportProgress(tr("Finished unmounting."));
@@ -274,6 +276,7 @@ void MaemoRemoteMounter::handleUtfsClientsFinished(int exitStatus)
void MaemoRemoteMounter::startUtfsServers() void MaemoRemoteMounter::startUtfsServers()
{ {
emit reportProgress(tr("Starting UTFS servers...")); emit reportProgress(tr("Starting UTFS servers..."));
m_utfsServerTimer->start(30000);
for (int i = 0; i < m_mountSpecs.count(); ++i) { for (int i = 0; i < m_mountSpecs.count(); ++i) {
const MountInfo &mountInfo = m_mountSpecs.at(i); const MountInfo &mountInfo = m_mountSpecs.at(i);
const MaemoMountSpecification &mountSpec = mountInfo.mountSpec; const MaemoMountSpecification &mountSpec = mountInfo.mountSpec;
@@ -281,29 +284,97 @@ void MaemoRemoteMounter::startUtfsServers()
const QString port = QString::number(mountInfo.remotePort); const QString port = QString::number(mountInfo.remotePort);
const QString localSecretOpt = QLatin1String("-l"); const QString localSecretOpt = QLatin1String("-l");
const QString remoteSecretOpt = QLatin1String("-r"); const QString remoteSecretOpt = QLatin1String("-r");
const QStringList utfsServerArgs = QStringList() const QStringList utfsServerArgs = QStringList() << localSecretOpt
<< QLatin1String("--detach") << localSecretOpt << port << port << remoteSecretOpt << port << QLatin1String("-c")
<< remoteSecretOpt << port << QLatin1String("-c")
<< (m_connection->connectionParameters().host + QLatin1Char(':') + port) << (m_connection->connectionParameters().host + QLatin1Char(':') + port)
<< mountSpec.localDir; << mountSpec.localDir;
connect(utfsServerProc.data(), SIGNAL(readyReadStandardError()), this,
SLOT(handleUtfsServerStderr()));
connect(utfsServerProc.data(),
SIGNAL(finished(int,QProcess::ExitStatus)), this,
SLOT(handleUtfsServerFinished(int,QProcess::ExitStatus)));
connect(utfsServerProc.data(), SIGNAL(error(QProcess::ProcessError)),
this, SLOT(handleUtfsServerError(QProcess::ProcessError)));
m_startedUtfsServers << utfsServerProc;
utfsServerProc->start(utfsServer(), utfsServerArgs); utfsServerProc->start(utfsServer(), utfsServerArgs);
if (!utfsServerProc->waitForStarted() }
|| !utfsServerProc->waitForFinished(5000)) { }
const QByteArray &errorOutput
= utfsServerProc->readAllStandardError(); void MaemoRemoteMounter::handleUtfsServerStderr()
QString errorMsg = tr("Could not start UTFS server: %1") {
.arg(utfsServerProc->errorString()); if (m_stop)
if (!errorOutput.isEmpty()) { return;
errorMsg += tr("\nstderr output was: '%1'")
.arg(QString::fromLocal8Bit(errorOutput)); for (int i = 0; i < m_startedUtfsServers.count(); ++i) {
UtfsServerInfo &info = m_startedUtfsServers[i];
if (info.proc.data() == sender()) {
info.output += info.proc->readAllStandardError();
if (info.output.contains("utfs server is ready")) {
m_readyUtfsServers << info;
m_startedUtfsServers.removeAt(i);
if (m_startedUtfsServers.isEmpty()) {
m_utfsServerTimer->stop();
emit mounted();
}
return;
} }
emit error(errorMsg); break;
return;
} }
m_utfsServers << utfsServerProc;
} }
emit mounted(); for (int i = 0; i < m_readyUtfsServers.count(); ++i) {
UtfsServerInfo &info = m_readyUtfsServers[i];
if (info.proc.data() == sender()) {
const QByteArray &output = info.proc->readAllStandardError();
qWarning("%s: %s", Q_FUNC_INFO, output.data());
info.output += output;
}
}
}
void MaemoRemoteMounter::handleUtfsServerError(QProcess::ProcessError procError)
{
if (procError != QProcess::FailedToStart)
return;
for (int i = 0; i < m_startedUtfsServers.count(); ++i) {
const UtfsServerInfo info = m_startedUtfsServers.at(i);
if (info.proc.data() == sender()) {
QString errorString = info.proc->errorString();
if (!info.output.isEmpty()) {
errorString += tr("\nstderr was: %1")
.arg(QString::fromLocal8Bit(info.output));
}
killAllUtfsServers();
m_utfsServerTimer->stop();
emit error(tr("Could not start UTFS server: %1").arg(errorString));
return;
}
}
qWarning("%s: Process failed to start", Q_FUNC_INFO);
}
void MaemoRemoteMounter::handleUtfsServerFinished(int exitCode,
QProcess::ExitStatus exitStatus)
{
if (exitStatus == QProcess::NormalExit && exitCode == 0)
return;
for (int i = 0; i < m_startedUtfsServers.count(); ++i) {
const UtfsServerInfo info = m_startedUtfsServers.at(i);
if (info.proc.data() == sender()) {
QString errorString = info.proc->errorString();
if (!info.output.isEmpty()) {
errorString += tr("\nstderr was: %1")
.arg(QString::fromLocal8Bit(info.output));
}
killAllUtfsServers();
m_utfsServerTimer->stop();
emit error(tr("UTFS server finished unexpectedly: %1").arg(errorString));
return;
}
}
} }
void MaemoRemoteMounter::handleUtfsClientStderr(const QByteArray &output) void MaemoRemoteMounter::handleUtfsClientStderr(const QByteArray &output)
@@ -327,5 +398,32 @@ QString MaemoRemoteMounter::utfsServer() const
return m_toolChain->maddeRoot() + QLatin1String("/madlib/utfs-server"); return m_toolChain->maddeRoot() + QLatin1String("/madlib/utfs-server");
} }
void MaemoRemoteMounter::killAllUtfsServers()
{
foreach (const UtfsServerInfo &info, m_startedUtfsServers)
killUtfsServer(info.proc.data());
m_startedUtfsServers.clear();
foreach (const UtfsServerInfo &info, m_readyUtfsServers)
killUtfsServer(info.proc.data());
m_readyUtfsServers.clear();
}
void MaemoRemoteMounter::killUtfsServer(QProcess *proc)
{
disconnect(proc, 0, this, 0);
proc->terminate();
proc->waitForFinished(1000);
proc->kill();
}
void MaemoRemoteMounter::handleUtfsServerTimeout()
{
if (m_stop)
return;
killAllUtfsServers();
emit error(tr("Timeout waiting for UTFS servers to connect."));
}
} // namespace Internal } // namespace Internal
} // namespace Qt4ProjectManager } // namespace Qt4ProjectManager

View File

@@ -37,10 +37,11 @@
#include <QtCore/QList> #include <QtCore/QList>
#include <QtCore/QObject> #include <QtCore/QObject>
#include <QtCore/QProcess>
#include <QtCore/QSharedPointer> #include <QtCore/QSharedPointer>
#include <QtCore/QString> #include <QtCore/QString>
QT_FORWARD_DECLARE_CLASS(QProcess); QT_FORWARD_DECLARE_CLASS(QTimer);
namespace Core { namespace Core {
class SftpChannel; class SftpChannel;
@@ -61,6 +62,7 @@ public:
void setPortList(const MaemoPortList &portList) { m_portList = portList; } void setPortList(const MaemoPortList &portList) { m_portList = portList; }
bool addMountSpecification(const MaemoMountSpecification &mountSpec, bool addMountSpecification(const MaemoMountSpecification &mountSpec,
bool mountAsRoot); bool mountAsRoot);
void resetMountSpecifications() { m_mountSpecs.clear(); }
void mount(); void mount();
void unmount(); void unmount();
void stop(); void stop();
@@ -81,16 +83,24 @@ private slots:
void handleUtfsClientsFinished(int exitStatus); void handleUtfsClientsFinished(int exitStatus);
void handleUnmountProcessFinished(int exitStatus); void handleUnmountProcessFinished(int exitStatus);
void handleUtfsClientStderr(const QByteArray &output); void handleUtfsClientStderr(const QByteArray &output);
void handleUtfsServerStderr();
void handleUtfsServerError(QProcess::ProcessError error);
void handleUtfsServerFinished(int exitCode,
QProcess::ExitStatus exitStatus);
void handleUmountStderr(const QByteArray &output); void handleUmountStderr(const QByteArray &output);
void handleUtfsServerTimeout();
private: private:
void deployUtfsClient(); void deployUtfsClient();
void startUtfsClients(); void startUtfsClients();
void startUtfsServers(); void startUtfsServers();
void killUtfsServer(QProcess *proc);
void killAllUtfsServers();
QString utfsClientOnDevice() const; QString utfsClientOnDevice() const;
QString utfsServer() const; QString utfsServer() const;
const MaemoToolChain * const m_toolChain; const MaemoToolChain * const m_toolChain;
QTimer * const m_utfsServerTimer;
struct MountInfo { struct MountInfo {
MountInfo(const MaemoMountSpecification &m, int port, bool root) MountInfo(const MaemoMountSpecification &m, int port, bool root)
@@ -108,7 +118,14 @@ private:
Core::SftpJobId m_uploadJobId; Core::SftpJobId m_uploadJobId;
typedef QSharedPointer<QProcess> ProcPtr; typedef QSharedPointer<QProcess> ProcPtr;
QList<ProcPtr> m_utfsServers; struct UtfsServerInfo {
UtfsServerInfo(const ProcPtr &p) : proc(p) {}
ProcPtr proc;
QByteArray output;
};
QList<UtfsServerInfo> m_startedUtfsServers;
QList<UtfsServerInfo> m_readyUtfsServers;
bool m_stop; bool m_stop;
QByteArray m_utfsClientStderr; QByteArray m_utfsClientStderr;
QByteArray m_umountStderr; QByteArray m_umountStderr;

View File

@@ -187,6 +187,7 @@ void MaemoSshRunner::handleUnmounted()
case InitialUnmount: { case InitialUnmount: {
if (m_stop) if (m_stop)
return; return;
m_mounter->resetMountSpecifications();
MaemoPortList portList = m_devConfig.freePorts(); MaemoPortList portList = m_devConfig.freePorts();
if (m_debugging && !m_runConfig->useRemoteGdb()) if (m_debugging && !m_runConfig->useRemoteGdb())
portList.getNext(); // One has already been used for gdbserver. portList.getNext(); // One has already been used for gdbserver.
@@ -214,6 +215,7 @@ void MaemoSshRunner::handleUnmounted()
break; break;
case ShutdownUnmount: case ShutdownUnmount:
Q_ASSERT(m_shuttingDown); Q_ASSERT(m_shuttingDown);
m_mounter->resetMountSpecifications();
m_shuttingDown = false; m_shuttingDown = false;
if (m_exitStatus == SshRemoteProcess::ExitedNormally) { if (m_exitStatus == SshRemoteProcess::ExitedNormally) {
emit remoteProcessFinished(m_runner->exitCode()); emit remoteProcessFinished(m_runner->exitCode());