diff options
Diffstat (limited to 'src/plugins/valgrind/valgrindprocess.cpp')
-rw-r--r-- | src/plugins/valgrind/valgrindprocess.cpp | 383 |
1 files changed, 166 insertions, 217 deletions
diff --git a/src/plugins/valgrind/valgrindprocess.cpp b/src/plugins/valgrind/valgrindprocess.cpp index 6fa61b288a..d112044e6c 100644 --- a/src/plugins/valgrind/valgrindprocess.cpp +++ b/src/plugins/valgrind/valgrindprocess.cpp @@ -35,6 +35,7 @@ #include <QFileInfo> #include <utils/qtcassert.h> +#include <utils/winutils.h> #ifdef Q_OS_WIN # include <qt_windows.h> @@ -42,191 +43,213 @@ namespace Valgrind { -ValgrindProcess::ValgrindProcess(QObject *parent) - : QObject(parent) +ValgrindProcess::ValgrindProcess(bool isLocal, const QSsh::SshConnectionParameters &sshParams, + QSsh::SshConnection *connection, QObject *parent) + : QObject(parent), m_isLocal(isLocal) { + m_remote.m_params = sshParams; + m_remote.m_connection = connection; + m_remote.m_error = QProcess::UnknownError; + m_pid = 0; } -//////////////////////// - -LocalValgrindProcess::LocalValgrindProcess(QObject *parent) -: ValgrindProcess(parent) +void ValgrindProcess::setProcessChannelMode(QProcess::ProcessChannelMode mode) { - connect(&m_process, SIGNAL(finished(int,QProcess::ExitStatus)), - this, SIGNAL(finished(int,QProcess::ExitStatus))); - connect(&m_process, SIGNAL(started()), - this, SIGNAL(started())); - connect(&m_process, SIGNAL(error(QProcess::ProcessError)), - this, SIGNAL(error(QProcess::ProcessError))); - connect(&m_process, SIGNAL(readyReadStandardError()), - this, SLOT(readyReadStandardError())); - connect(&m_process, SIGNAL(readyReadStandardOutput()), - this, SLOT(readyReadStandardOutput())); + if (isLocal()) + m_localProcess.setProcessChannelMode(mode); + ///TODO: remote support this by handling the mode internally } -void LocalValgrindProcess::setProcessChannelMode(QProcess::ProcessChannelMode mode) +void ValgrindProcess::setWorkingDirectory(const QString &path) { - m_process.setProcessChannelMode(mode); + if (isLocal()) + m_localProcess.setWorkingDirectory(path); + else + m_remote.m_workingDir = path; } -void LocalValgrindProcess::setWorkingDirectory(const QString &path) +QString ValgrindProcess::workingDirectory() const { - m_process.setWorkingDirectory(path); + if (isLocal()) + return m_localProcess.workingDirectory(); + else + return m_remote.m_workingDir; } -QString LocalValgrindProcess::workingDirectory() const +bool ValgrindProcess::isRunning() const { - return m_process.workingDirectory(); + if (isLocal()) + return m_localProcess.state() != QProcess::NotRunning; + else + return m_remote.m_process && m_remote.m_process->isRunning(); } -bool LocalValgrindProcess::isRunning() const +void ValgrindProcess::setEnvironment(const Utils::Environment &environment) { - return m_process.state() != QProcess::NotRunning; + if (isLocal()) + m_localProcess.setEnvironment(environment); + ///TODO: remote anything that should/could be done here? } -void LocalValgrindProcess::setEnvironment(const Utils::Environment &environment) +void ValgrindProcess::close() { - m_process.setEnvironment(environment); + if (isLocal()) { + m_localProcess.terminate(); + } else { + QTC_ASSERT(m_remote.m_connection->state() == QSsh::SshConnection::Connected, return); + if (m_remote.m_process) { + if (m_pid) { + const QString killTemplate = QString::fromLatin1("kill -%2 %1" // kill + ).arg(m_pid); + + const QString niceKill = killTemplate.arg(QLatin1String("SIGTERM")); + const QString brutalKill = killTemplate.arg(QLatin1String("SIGKILL")); + const QString remoteCall = niceKill + QLatin1String("; sleep 1; ") + brutalKill; + + QSsh::SshRemoteProcess::Ptr cleanup = m_remote.m_connection->createRemoteProcess(remoteCall.toUtf8()); + cleanup->start(); + } + } + } } -void LocalValgrindProcess::close() +void ValgrindProcess::run(const QString &valgrindExecutable, const QStringList &valgrindArguments, + const QString &debuggeeExecutable, const QString &debuggeeArguments) { - m_process.terminate(); + Utils::QtcProcess::addArgs(&m_arguments, valgrindArguments); + Utils::QtcProcess::addArg(&m_arguments, debuggeeExecutable); + Utils::QtcProcess::addArgs(&m_arguments, debuggeeArguments); + + if (isLocal()) { + connect(&m_localProcess, SIGNAL(finished(int,QProcess::ExitStatus)), + this, SIGNAL(finished(int,QProcess::ExitStatus))); + connect(&m_localProcess, SIGNAL(started()), + this, SIGNAL(started())); + connect(&m_localProcess, SIGNAL(error(QProcess::ProcessError)), + this, SIGNAL(error(QProcess::ProcessError))); + connect(&m_localProcess, SIGNAL(readyReadStandardError()), + this, SLOT(handleReadyReadStandardError())); + connect(&m_localProcess, SIGNAL(readyReadStandardOutput()), + this, SLOT(handleReadyReadStandardOutput())); + + m_localProcess.setCommand(valgrindExecutable, m_arguments); + m_localProcess.start(); + m_localProcess.waitForStarted(); + m_pid = Utils::qPidToPid(m_localProcess.pid()); + } else { + m_remote.m_valgrindExe = valgrindExecutable; + m_remote.m_debuggee = debuggeeExecutable; + + // connect to host and wait for connection + if (!m_remote.m_connection) + m_remote.m_connection = new QSsh::SshConnection(m_remote.m_params, this); + + if (m_remote.m_connection->state() != QSsh::SshConnection::Connected) { + connect(m_remote.m_connection, SIGNAL(connected()), this, SLOT(connected())); + connect(m_remote.m_connection, SIGNAL(error(QSsh::SshError)), + this, SLOT(handelError(QSsh::SshError))); + if (m_remote.m_connection->state() == QSsh::SshConnection::Unconnected) + m_remote.m_connection->connectToHost(); + } else { + connected(); + } + } } -void LocalValgrindProcess::run(const QString &valgrindExecutable, const QStringList &valgrindArguments, - const QString &debuggeeExecutable, const QString &debuggeeArguments) +QString ValgrindProcess::errorString() const { - QString arguments; - Utils::QtcProcess::addArgs(&arguments, valgrindArguments); - - Utils::QtcProcess::addArg(&arguments, debuggeeExecutable); - Utils::QtcProcess::addArgs(&arguments, debuggeeArguments); - - m_process.setCommand(valgrindExecutable, arguments); - m_process.start(); - m_process.waitForStarted(); -#ifdef Q_OS_WIN - m_pid = m_process.pid()->dwProcessId; -#else - m_pid = m_process.pid(); -#endif + if (isLocal()) + return m_localProcess.errorString(); + else + return m_remote.m_errorString; } -QString LocalValgrindProcess::errorString() const +QProcess::ProcessError ValgrindProcess::error() const { - return m_process.errorString(); + if (isLocal()) + return m_localProcess.error(); + else + return m_remote.m_error; } -QProcess::ProcessError LocalValgrindProcess::error() const +void ValgrindProcess::handleError(QSsh::SshError error) { - return m_process.error(); + if (isLocal()) { + } else { + switch (error) { + case QSsh::SshTimeoutError: + m_remote.m_error = QProcess::Timedout; + break; + default: + m_remote.m_error = QProcess::FailedToStart; + break; + } + } + m_remote.m_errorString = m_remote.m_connection->errorString(); + emit this->error(m_remote.m_error); } -qint64 LocalValgrindProcess::pid() const +qint64 ValgrindProcess::pid() const { return m_pid; } -void LocalValgrindProcess::readyReadStandardError() +void ValgrindProcess::handleReadyReadStandardError() { - const QByteArray b = m_process.readAllStandardError(); + QByteArray b; + if (isLocal()) + b = m_localProcess.readAllStandardError(); + else + b = m_remote.m_process->readAllStandardError(); if (!b.isEmpty()) emit processOutput(b, Utils::StdErrFormat); } -void LocalValgrindProcess::readyReadStandardOutput() +void ValgrindProcess::handleReadyReadStandardOutput() { - const QByteArray b = m_process.readAllStandardOutput(); + QByteArray b; + if (isLocal()) + b = m_localProcess.readAllStandardOutput(); + else + b = m_remote.m_process->readAllStandardOutput(); if (!b.isEmpty()) emit processOutput(b, Utils::StdOutFormat); } -//////////////////////// - -RemoteValgrindProcess::RemoteValgrindProcess(const QSsh::SshConnectionParameters &sshParams, - QObject *parent) - : ValgrindProcess(parent) - , m_params(sshParams) - , m_connection(0) - , m_error(QProcess::UnknownError) - , m_pid(0) -{} - -RemoteValgrindProcess::RemoteValgrindProcess(QSsh::SshConnection *connection, QObject *parent) - : ValgrindProcess(parent) - , m_params(connection->connectionParameters()) - , m_connection(connection) - , m_error(QProcess::UnknownError) - , m_pid(0) -{} - -RemoteValgrindProcess::~RemoteValgrindProcess() +/// Remote +void ValgrindProcess::connected() { -} - -bool RemoteValgrindProcess::isRunning() const -{ - return m_process && m_process->isRunning(); -} - -void RemoteValgrindProcess::run(const QString &valgrindExecutable, const QStringList &valgrindArguments, - const QString &debuggeeExecutable, const QString &debuggeeArguments) -{ - m_valgrindExe = valgrindExecutable; - m_debuggee = debuggeeExecutable; - m_debuggeeArgs = debuggeeArguments; - m_valgrindArgs = valgrindArguments; - - // connect to host and wait for connection - if (!m_connection) - m_connection = new QSsh::SshConnection(m_params, this); - - if (m_connection->state() != QSsh::SshConnection::Connected) { - connect(m_connection, SIGNAL(connected()), this, SLOT(connected())); - connect(m_connection, SIGNAL(error(QSsh::SshError)), - this, SLOT(error(QSsh::SshError))); - if (m_connection->state() == QSsh::SshConnection::Unconnected) - m_connection->connectToHost(); - } else { - connected(); - } -} - -void RemoteValgrindProcess::connected() -{ - QTC_ASSERT(m_connection->state() == QSsh::SshConnection::Connected, return); + QTC_ASSERT(m_remote.m_connection->state() == QSsh::SshConnection::Connected, return); // connected, run command QString cmd; - if (!m_workingDir.isEmpty()) - cmd += QString::fromLatin1("cd '%1' && ").arg(m_workingDir); + if (!m_remote.m_workingDir.isEmpty()) + cmd += QString::fromLatin1("cd '%1' && ").arg(m_remote.m_workingDir); - QString arguments; - Utils::QtcProcess::addArgs(&arguments, m_valgrindArgs); - Utils::QtcProcess::addArg(&arguments, m_debuggee); - Utils::QtcProcess::addArgs(&arguments, m_debuggeeArgs); - cmd += m_valgrindExe + QLatin1Char(' ') + arguments; + cmd += m_remote.m_valgrindExe + QLatin1Char(' ') + m_arguments; - m_process = m_connection->createRemoteProcess(cmd.toUtf8()); - connect(m_process.data(), SIGNAL(readyReadStandardError()), this, SLOT(standardError())); - connect(m_process.data(), SIGNAL(readyReadStandardOutput()), this, SLOT(standardOutput())); - connect(m_process.data(), SIGNAL(closed(int)), + m_remote.m_process = m_remote.m_connection->createRemoteProcess(cmd.toUtf8()); + connect(m_remote.m_process.data(), SIGNAL(readyReadStandardError()), + this, SLOT(handleReadyReadStandardError())); + connect(m_remote.m_process.data(), SIGNAL(readyReadStandardOutput()), + this, SLOT(handleReadyReadStandardOutput())); + connect(m_remote.m_process.data(), SIGNAL(closed(int)), this, SLOT(closed(int))); - connect(m_process.data(), SIGNAL(started()), + connect(m_remote.m_process.data(), SIGNAL(started()), this, SLOT(processStarted())); - m_process->start(); + m_remote.m_process->start(); } -QSsh::SshConnection *RemoteValgrindProcess::connection() const + +QSsh::SshConnection *ValgrindProcess::connection() const { - return m_connection; + return m_remote.m_connection; } -void RemoteValgrindProcess::processStarted() +void ValgrindProcess::processStarted() { - QTC_ASSERT(m_connection->state() == QSsh::SshConnection::Connected, return); + QTC_ASSERT(m_remote.m_connection->state() == QSsh::SshConnection::Connected, return); // find out what PID our process has @@ -237,7 +260,7 @@ void RemoteValgrindProcess::processStarted() // hence we need to do something more complex... // plain path to exe, m_valgrindExe contains e.g. env vars etc. pp. - const QString proc = m_valgrindExe.split(QLatin1Char(' ')).last(); + const QString proc = m_remote.m_valgrindExe.split(QLatin1Char(' ')).last(); // sleep required since otherwise we might only match "bash -c..." // and not the actual valgrind run const QString cmd = QString::fromLatin1("sleep 1; ps ax" // list all processes with aliased name @@ -245,22 +268,24 @@ void RemoteValgrindProcess::processStarted() " | tail -n 1" // limit to single process // we pick the last one, first would be "bash -c ..." " | awk '{print $1;}'" // get pid - ).arg(proc, QFileInfo(m_debuggee).fileName()); + ).arg(proc, QFileInfo(m_remote.m_debuggee).fileName()); - m_findPID = m_connection->createRemoteProcess(cmd.toUtf8()); - connect(m_findPID.data(), SIGNAL(readyReadStandardError()), this, SLOT(standardError())); - connect(m_findPID.data(), SIGNAL(readyReadStandardOutput()), SLOT(findPIDOutputReceived())); - m_findPID->start(); + m_remote.m_findPID = m_remote.m_connection->createRemoteProcess(cmd.toUtf8()); + connect(m_remote.m_findPID.data(), SIGNAL(readyReadStandardError()), + this, SLOT(handleReadyReadStandardError())); + connect(m_remote.m_findPID.data(), SIGNAL(readyReadStandardOutput()), + this, SLOT(findPIDOutputReceived())); + m_remote.m_findPID->start(); } -void RemoteValgrindProcess::findPIDOutputReceived() +void ValgrindProcess::findPIDOutputReceived() { bool ok; - m_pid = m_findPID->readAllStandardOutput().trimmed().toLongLong(&ok); + m_pid = m_remote.m_findPID->readAllStandardOutput().trimmed().toLongLong(&ok); if (!ok) { m_pid = 0; - m_errorString = tr("Could not determine remote PID."); - m_error = QProcess::FailedToStart; + m_remote.m_errorString = tr("Could not determine remote PID."); + m_remote.m_error = QProcess::FailedToStart; emit ValgrindProcess::error(QProcess::FailedToStart); close(); } else { @@ -268,99 +293,23 @@ void RemoteValgrindProcess::findPIDOutputReceived() } } -void RemoteValgrindProcess::standardOutput() -{ - emit processOutput(m_process->readAllStandardOutput(), Utils::StdOutFormat); -} - -void RemoteValgrindProcess::standardError() -{ - emit processOutput(m_process->readAllStandardError(), Utils::StdErrFormat); -} - -void RemoteValgrindProcess::error(QSsh::SshError error) -{ - switch (error) { - case QSsh::SshTimeoutError: - m_error = QProcess::Timedout; - break; - default: - m_error = QProcess::FailedToStart; - break; - } - m_errorString = m_connection->errorString(); - emit ValgrindProcess::error(m_error); -} -void RemoteValgrindProcess::close() -{ - QTC_ASSERT(m_connection->state() == QSsh::SshConnection::Connected, return); - if (m_process) { - if (m_pid) { - const QString killTemplate = QString::fromLatin1("kill -%2 %1" // kill - ).arg(m_pid); - - const QString niceKill = killTemplate.arg(QLatin1String("SIGTERM")); - const QString brutalKill = killTemplate.arg(QLatin1String("SIGKILL")); - const QString remoteCall = niceKill + QLatin1String("; sleep 1; ") + brutalKill; - - QSsh::SshRemoteProcess::Ptr cleanup = m_connection->createRemoteProcess(remoteCall.toUtf8()); - cleanup->start(); - } - } -} +/////////// -void RemoteValgrindProcess::closed(int status) +void ValgrindProcess::closed(int status) { - QTC_ASSERT(m_process, return); + QTC_ASSERT(m_remote.m_process, return); - m_errorString = m_process->errorString(); + m_remote.m_errorString = m_remote.m_process->errorString(); if (status == QSsh::SshRemoteProcess::FailedToStart) { - m_error = QProcess::FailedToStart; + m_remote.m_error = QProcess::FailedToStart; emit ValgrindProcess::error(QProcess::FailedToStart); } else if (status == QSsh::SshRemoteProcess::NormalExit) { - emit finished(m_process->exitCode(), QProcess::NormalExit); + emit finished(m_remote.m_process->exitCode(), QProcess::NormalExit); } else if (status == QSsh::SshRemoteProcess::CrashExit) { - m_error = QProcess::Crashed; - emit finished(m_process->exitCode(), QProcess::CrashExit); + m_remote.m_error = QProcess::Crashed; + emit finished(m_remote.m_process->exitCode(), QProcess::CrashExit); } } -QString RemoteValgrindProcess::errorString() const -{ - return m_errorString; -} - -QProcess::ProcessError RemoteValgrindProcess::error() const -{ - return m_error; -} - -void RemoteValgrindProcess::setEnvironment(const Utils::Environment &environment) -{ - Q_UNUSED(environment); - ///TODO: anything that should/could be done here? -} - -void RemoteValgrindProcess::setProcessChannelMode(QProcess::ProcessChannelMode mode) -{ - Q_UNUSED(mode); - ///TODO: support this by handling the mode internally -} - -void RemoteValgrindProcess::setWorkingDirectory(const QString &path) -{ - m_workingDir = path; -} - -QString RemoteValgrindProcess::workingDirectory() const -{ - return m_workingDir; -} - -qint64 RemoteValgrindProcess::pid() const -{ - return m_pid; -} - } // namespace Valgrind |