diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp index ebb839fc907bedb05b19dacbbb1b398152ae8dff..2195708fd9f3dd4f242275b1a1074feedf9822ce 100644 --- a/src/plugins/debugger/debuggerruncontrol.cpp +++ b/src/plugins/debugger/debuggerruncontrol.cpp @@ -468,12 +468,24 @@ static DebuggerRunConfigurationAspect *debuggerAspect(const RunControl *runContr return runControl->runConfiguration()->extraAspect<DebuggerRunConfigurationAspect>(); } +static bool cppDebugging(const RunControl *runControl) +{ + auto aspect = debuggerAspect(runControl); + return aspect ? aspect->useCppDebugger() : true; // For cases like valgrind-with-gdb. +} + +static bool qmlDebugging(const RunControl *runControl) +{ + auto aspect = debuggerAspect(runControl); + return aspect ? aspect->useCppDebugger() : false; // For cases like valgrind-with-gdb. +} + /// DebuggerRunTool DebuggerRunTool::DebuggerRunTool(RunControl *runControl) : RunWorker(runControl), - m_isCppDebugging(debuggerAspect(runControl)->useCppDebugger()), - m_isQmlDebugging(debuggerAspect(runControl)->useQmlDebugger()) + m_isCppDebugging(cppDebugging(runControl)), + m_isQmlDebugging(qmlDebugging(runControl)) { setDisplayName("DebuggerRunTool"); } diff --git a/src/plugins/valgrind/callgrind/callgrindcontroller.cpp b/src/plugins/valgrind/callgrind/callgrindcontroller.cpp index faf1c980b4d6d7e96d7b5810b9a95f7cf84d87c9..b28c5a98af77e1a92a13d0e59153a50e4c568e1f 100644 --- a/src/plugins/valgrind/callgrind/callgrindcontroller.cpp +++ b/src/plugins/valgrind/callgrind/callgrindcontroller.cpp @@ -192,15 +192,15 @@ void CallgrindController::getLocalDataFile() QString fileName = workingDir.isEmpty() ? baseFileName : (workingDir + QLatin1Char('/') + baseFileName); if (!m_valgrindProc->isLocal()) { - ///TODO: error handling - emit statusMessage(tr("Downloading remote profile data...")); - m_ssh = m_valgrindProc->connection(); - // if there are files like callgrind.out.PID.NUM, set it to the most recent one of those - QString cmd = QString::fromLatin1("ls -t %1* | head -n 1").arg(fileName); - m_findRemoteFile = m_ssh->createRemoteProcess(cmd.toUtf8()); - connect(m_findRemoteFile.data(), &QSsh::SshRemoteProcess::readyReadStandardOutput, - this, &CallgrindController::foundRemoteFile); - m_findRemoteFile->start(); +// ///TODO: error handling +// emit statusMessage(tr("Downloading remote profile data...")); +// m_ssh = m_valgrindProc->connection(); +// // if there are files like callgrind.out.PID.NUM, set it to the most recent one of those +// QString cmd = QString::fromLatin1("ls -t %1* | head -n 1").arg(fileName); +// m_findRemoteFile = m_ssh->createRemoteProcess(cmd.toUtf8()); +// connect(m_findRemoteFile.data(), &QSsh::SshRemoteProcess::readyReadStandardOutput, +// this, &CallgrindController::foundRemoteFile); +// m_findRemoteFile->start(); } else { QDir dir(workingDir, QString::fromLatin1("%1.*").arg(baseFileName), QDir::Time); QStringList outputFiles = dir.entryList(); diff --git a/src/plugins/valgrind/memcheckengine.cpp b/src/plugins/valgrind/memcheckengine.cpp index d6f44798e295dbfbe256c7839c9c61c9daee5475..918abbcb2a3a9e5b91060056b2f8bf25d4f3f279 100644 --- a/src/plugins/valgrind/memcheckengine.cpp +++ b/src/plugins/valgrind/memcheckengine.cpp @@ -51,8 +51,33 @@ using namespace Valgrind::XmlProtocol; namespace Valgrind { namespace Internal { +class LocalAddressFinder : public RunWorker +{ +public: + LocalAddressFinder(RunControl *runControl, QHostAddress *localServerAddress) + : RunWorker(runControl), connection(device()->sshParameters()) + { + connect(&connection, &QSsh::SshConnection::connected, this, [this, localServerAddress] { + *localServerAddress = connection.connectionInfo().localAddress; + reportStarted(); + }); + connect(&connection, &QSsh::SshConnection::error, this, [this] { + reportFailure(); + }); + } + + void start() override + { + connection.connectToHost(); + } + + QSsh::SshConnection connection; +}; + MemcheckToolRunner::MemcheckToolRunner(RunControl *runControl, bool withGdb) - : ValgrindToolRunner(runControl), m_withGdb(withGdb) + : ValgrindToolRunner(runControl), + m_withGdb(withGdb), + m_localServerAddress(QHostAddress::LocalHost) { setDisplayName("MemcheckToolRunner"); connect(m_runner.parser(), &XmlProtocol::ThreadedParser::error, @@ -65,11 +90,15 @@ MemcheckToolRunner::MemcheckToolRunner(RunControl *runControl, bool withGdb) this, &MemcheckToolRunner::startDebugger); connect(&m_runner, &ValgrindRunner::logMessageReceived, this, &MemcheckToolRunner::appendLog); - m_runner.disableXml(); +// m_runner.disableXml(); } else { connect(m_runner.parser(), &XmlProtocol::ThreadedParser::internalError, this, &MemcheckToolRunner::internalParserError); } + + // We need a real address to connect to from the outside. + if (device()->type() != ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) + addDependency(new LocalAddressFinder(runControl, &m_localServerAddress)); } QString MemcheckToolRunner::progressTitle() const @@ -79,10 +108,7 @@ QString MemcheckToolRunner::progressTitle() const void MemcheckToolRunner::start() { -// MemcheckTool::engineStarting(this); - - appendMessage(tr("Analyzing memory of %1").arg(executable()) + QLatin1Char('\n'), - Utils::NormalMessageFormat); + m_runner.setLocalServerAddress(m_localServerAddress); ValgrindToolRunner::start(); } @@ -149,12 +175,10 @@ void MemcheckToolRunner::startDebugger() sp.useContinueInsteadOfRun = true; sp.expectedSignals.append("SIGTRAP"); - QString errorMessage; - auto gdbRunControl = new RunControl(nullptr, ProjectExplorer::Constants::DEBUG_RUN_MODE); - (void) new Debugger::DebuggerRunTool(gdbRunControl, sp, &errorMessage); - connect(gdbRunControl, &RunControl::finished, - gdbRunControl, &RunControl::deleteLater); - gdbRunControl->initiateStart(); + auto gdbWorker = new Debugger::DebuggerRunTool(runControl()); + gdbWorker->setStartParameters(sp); + gdbWorker->initiateStart(); + connect(runControl(), &RunControl::finished, gdbWorker, &RunControl::deleteLater); } void MemcheckToolRunner::appendLog(const QByteArray &data) diff --git a/src/plugins/valgrind/memcheckengine.h b/src/plugins/valgrind/memcheckengine.h index e77d4ec02d6dfd51268ff256ad8d796c63fc3716..40d97ac7038154fe69bd8ed16de2459f211cfb7c 100644 --- a/src/plugins/valgrind/memcheckengine.h +++ b/src/plugins/valgrind/memcheckengine.h @@ -60,6 +60,7 @@ private: void appendLog(const QByteArray &data); const bool m_withGdb; + QHostAddress m_localServerAddress; }; } // namespace Internal diff --git a/src/plugins/valgrind/valgrindengine.cpp b/src/plugins/valgrind/valgrindengine.cpp index 649a1d75948257b84701cf4dbdbc1baa5ea9e25f..b87728ba4829fce8abe46671741a6fee8ced48ad 100644 --- a/src/plugins/valgrind/valgrindengine.cpp +++ b/src/plugins/valgrind/valgrindengine.cpp @@ -106,6 +106,7 @@ void ValgrindToolRunner::stop() { m_isStopping = true; m_runner.stop(); + reportStopped(); // FIXME: Restrict to non-running scenarios? } QString ValgrindToolRunner::executable() const diff --git a/src/plugins/valgrind/valgrindprocess.cpp b/src/plugins/valgrind/valgrindprocess.cpp index 5f45c90bb155cd517b0e517862b01fb97b631213..e0fa607c282e6b0cc08ed892bf5aa7fc1585fa5e 100644 --- a/src/plugins/valgrind/valgrindprocess.cpp +++ b/src/plugins/valgrind/valgrindprocess.cpp @@ -39,26 +39,18 @@ using namespace ProjectExplorer; namespace Valgrind { -ValgrindProcess::ValgrindProcess(const IDevice::ConstPtr &device, - QObject *parent) +ValgrindProcess::ValgrindProcess(const IDevice::ConstPtr &device, QObject *parent) : QObject(parent), m_device(device) { - m_remote.m_connection = 0; - m_remote.m_error = QProcess::UnknownError; - m_pid = 0; } ValgrindProcess::~ValgrindProcess() { - if (m_remote.m_connection) - QSsh::releaseConnection(m_remote.m_connection); } void ValgrindProcess::setProcessChannelMode(QProcess::ProcessChannelMode mode) { - if (isLocal()) - m_localProcess.setProcessChannelMode(mode); - ///TODO: remote support this by handling the mode internally + m_valgrindProcess.setProcessChannelMode(mode); } QString ValgrindProcess::workingDirectory() const @@ -68,10 +60,7 @@ QString ValgrindProcess::workingDirectory() const bool ValgrindProcess::isRunning() const { - if (isLocal()) - return m_localProcess.isRunning(); - else - return m_remote.m_process && m_remote.m_process->isRunning(); + return m_valgrindProcess.isRunning(); } void ValgrindProcess::setValgrindExecutable(const QString &valgrindExecutable) @@ -91,94 +80,53 @@ void ValgrindProcess::setValgrindArguments(const QStringList &valgrindArguments) void ValgrindProcess::close() { - if (isLocal()) { - m_localProcess.stop(); - } 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(); - } - } - } + m_valgrindProcess.stop(); } void ValgrindProcess::run(ApplicationLauncher::Mode runMode) { + connect(&m_valgrindProcess, &ApplicationLauncher::processExited, + this, &ValgrindProcess::finished); + connect(&m_valgrindProcess, &ApplicationLauncher::processStarted, + this, &ValgrindProcess::localProcessStarted); + connect(&m_valgrindProcess, &ApplicationLauncher::error, + this, &ValgrindProcess::error); + connect(&m_valgrindProcess, &ApplicationLauncher::appendMessage, + this, &ValgrindProcess::processOutput); + + connect(&m_valgrindProcess, &ApplicationLauncher::remoteStderr, + this, &ValgrindProcess::handleRemoteStderr); + connect(&m_valgrindProcess, &ApplicationLauncher::remoteStdout, + this, &ValgrindProcess::handleRemoteStdout); + connect(&m_valgrindProcess, &ApplicationLauncher::finished, + this, &ValgrindProcess::closed); + connect(&m_valgrindProcess, &ApplicationLauncher::remoteProcessStarted, + this, &ValgrindProcess::remoteProcessStarted); + + StandardRunnable valgrind; + valgrind.executable = m_valgrindExecutable; + valgrind.workingDirectory = m_debuggee.workingDirectory; + valgrind.environment = m_debuggee.environment; + valgrind.runMode = runMode; + valgrind.device = m_device; + if (isLocal()) { - connect(&m_localProcess, &ApplicationLauncher::processExited, - this, &ValgrindProcess::finished); - connect(&m_localProcess, &ApplicationLauncher::processStarted, - this, &ValgrindProcess::localProcessStarted); - connect(&m_localProcess, &ApplicationLauncher::error, - this, &ValgrindProcess::error); - connect(&m_localProcess, &ApplicationLauncher::appendMessage, - this, &ValgrindProcess::processOutput); - - StandardRunnable valgrind; - valgrind.executable = m_valgrindExecutable; - valgrind.runMode = runMode; valgrind.commandLineArguments = argumentString(Utils::HostOsInfo::hostOs()); - valgrind.workingDirectory = m_debuggee.workingDirectory; - valgrind.environment = m_debuggee.environment; - m_localProcess.start(valgrind); - + m_valgrindProcess.start(valgrind); } else { - // connect to host and wait for connection - if (!m_remote.m_connection) - m_remote.m_connection = QSsh::acquireConnection(m_device->sshParameters()); - - if (m_remote.m_connection->state() != QSsh::SshConnection::Connected) { - connect(m_remote.m_connection, &QSsh::SshConnection::connected, - this, &ValgrindProcess::connected); - connect(m_remote.m_connection, &QSsh::SshConnection::error, - this, &ValgrindProcess::handleError); - if (m_remote.m_connection->state() == QSsh::SshConnection::Unconnected) - m_remote.m_connection->connectToHost(); - } else { - connected(); - } + valgrind.commandLineArguments = argumentString(Utils::OsTypeLinux); + m_valgrindProcess.start(valgrind, m_device); } } QString ValgrindProcess::errorString() const { - if (isLocal()) - return m_localProcess.errorString(); - else - return m_remote.m_errorString; + return m_valgrindProcess.errorString(); } QProcess::ProcessError ValgrindProcess::processError() const { - if (isLocal()) - return m_localProcess.processError(); - else - return m_remote.m_error; -} - -void ValgrindProcess::handleError(QSsh::SshError error) -{ - if (!isLocal()) { - 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); + return m_valgrindProcess.processError(); } qint64 ValgrindProcess::pid() const @@ -186,53 +134,16 @@ qint64 ValgrindProcess::pid() const return m_pid; } -void ValgrindProcess::handleRemoteStderr() +void ValgrindProcess::handleRemoteStderr(const QByteArray &b) { - const QString b = QString::fromUtf8(m_remote.m_process->readAllStandardError()); if (!b.isEmpty()) - emit processOutput(b, Utils::StdErrFormat); + emit processOutput(QString::fromUtf8(b), Utils::StdErrFormat); } -void ValgrindProcess::handleRemoteStdout() +void ValgrindProcess::handleRemoteStdout(const QByteArray &b) { - const QString b = QString::fromUtf8(m_remote.m_process->readAllStandardOutput()); if (!b.isEmpty()) - emit processOutput(b, Utils::StdOutFormat); -} - -/// Remote -void ValgrindProcess::connected() -{ - QTC_ASSERT(m_remote.m_connection->state() == QSsh::SshConnection::Connected, return); - - emit localHostAddressRetrieved(m_remote.m_connection->connectionInfo().localAddress); - - // connected, run command - QString cmd; - - if (!m_debuggee.workingDirectory.isEmpty()) - cmd += QString::fromLatin1("cd '%1' && ").arg(m_debuggee.workingDirectory); - - cmd += m_valgrindExecutable + QLatin1Char(' ') + argumentString(Utils::OsTypeLinux); - - m_remote.m_process = m_remote.m_connection->createRemoteProcess(cmd.toUtf8()); - for (auto it = m_debuggee.environment.constBegin(); it != m_debuggee.environment.constEnd(); ++it) - m_remote.m_process->addToEnvironment(it.key().toUtf8(), it.value().toUtf8()); - - connect(m_remote.m_process.data(), &QSsh::SshRemoteProcess::readyReadStandardError, - this, &ValgrindProcess::handleRemoteStderr); - connect(m_remote.m_process.data(), &QSsh::SshRemoteProcess::readyReadStandardOutput, - this, &ValgrindProcess::handleRemoteStdout); - connect(m_remote.m_process.data(), &QSsh::SshRemoteProcess::closed, - this, &ValgrindProcess::closed); - connect(m_remote.m_process.data(), &QSsh::SshRemoteProcess::started, - this, &ValgrindProcess::remoteProcessStarted); - m_remote.m_process->start(); -} - -QSsh::SshConnection *ValgrindProcess::connection() const -{ - return m_remote.m_connection; + emit processOutput(QString::fromUtf8(b), Utils::StdOutFormat); } bool ValgrindProcess::isLocal() const @@ -242,14 +153,12 @@ bool ValgrindProcess::isLocal() const void ValgrindProcess::localProcessStarted() { - m_pid = m_localProcess.applicationPID().pid(); + m_pid = m_valgrindProcess.applicationPID().pid(); emit started(); } void ValgrindProcess::remoteProcessStarted() { - QTC_ASSERT(m_remote.m_connection->state() == QSsh::SshConnection::Connected, return); - // find out what PID our process has // NOTE: valgrind cloaks its name, @@ -259,34 +168,40 @@ void ValgrindProcess::remoteProcessStarted() // 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_valgrindExecutable.split(QLatin1Char(' ')).last(); + const QString proc = m_valgrindExecutable.split(' ').last(); + + StandardRunnable findPid; + findPid.executable = "/bin/sh"; // 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 - " | grep '\\b%1.*%2'" // find valgrind process - " | tail -n 1" // limit to single process - // we pick the last one, first would be "bash -c ..." - " | awk '{print $1;}'" // get pid - ).arg(proc, Utils::FileName::fromString(m_debuggee.executable).fileName()); - - m_remote.m_findPID = m_remote.m_connection->createRemoteProcess(cmd.toUtf8()); - connect(m_remote.m_findPID.data(), &QSsh::SshRemoteProcess::readyReadStandardError, + findPid.commandLineArguments = QString("-c \"" + "sleep 1; ps ax" // list all processes with aliased name + " | grep '\\b%1.*%2'" // find valgrind process + " | tail -n 1" // limit to single process + // we pick the last one, first would be "bash -c ..." + " | awk '{print $1;}'" // get pid + "\"" + ).arg(proc, Utils::FileName::fromString(m_debuggee.executable).fileName()); + +// m_remote.m_findPID = m_remote.m_connection->createRemoteProcess(cmd.toUtf8()); + connect(&m_findPID, &ApplicationLauncher::remoteStderr, this, &ValgrindProcess::handleRemoteStderr); - connect(m_remote.m_findPID.data(), &QSsh::SshRemoteProcess::readyReadStandardOutput, + connect(&m_findPID, &ApplicationLauncher::remoteStdout, this, &ValgrindProcess::findPIDOutputReceived); - m_remote.m_findPID->start(); + m_findPID.start(findPid, m_device); } -void ValgrindProcess::findPIDOutputReceived() +void ValgrindProcess::findPIDOutputReceived(const QByteArray &out) { + if (out.isEmpty()) + return; bool ok; - m_pid = m_remote.m_findPID->readAllStandardOutput().trimmed().toLongLong(&ok); + m_pid = out.trimmed().toLongLong(&ok); if (!ok) { m_pid = 0; - m_remote.m_errorString = tr("Could not determine remote PID."); - m_remote.m_error = QProcess::FailedToStart; - emit ValgrindProcess::error(QProcess::FailedToStart); - close(); +// m_remote.m_errorString = tr("Could not determine remote PID."); +// emit ValgrindProcess::error(QProcess::FailedToStart); +// close(); } else { emit started(); } @@ -301,20 +216,22 @@ QString ValgrindProcess::argumentString(Utils::OsType osType) const return arguments; } -void ValgrindProcess::closed(int status) +void ValgrindProcess::closed(bool success) { - QTC_ASSERT(m_remote.m_process, return); - - m_remote.m_errorString = m_remote.m_process->errorString(); - if (status == QSsh::SshRemoteProcess::FailedToStart) { - m_remote.m_error = QProcess::FailedToStart; - emit ValgrindProcess::error(QProcess::FailedToStart); - } else if (status == QSsh::SshRemoteProcess::NormalExit) { - emit finished(m_remote.m_process->exitCode(), QProcess::NormalExit); - } else if (status == QSsh::SshRemoteProcess::CrashExit) { - m_remote.m_error = QProcess::Crashed; - emit finished(m_remote.m_process->exitCode(), QProcess::CrashExit); - } + Q_UNUSED(success); +// QTC_ASSERT(m_remote.m_process, return); + +// m_remote.m_errorString = m_remote.m_process->errorString(); +// if (status == QSsh::SshRemoteProcess::FailedToStart) { +// m_remote.m_error = QProcess::FailedToStart; +// emit ValgrindProcess::error(QProcess::FailedToStart); +// } else if (status == QSsh::SshRemoteProcess::NormalExit) { +// emit finished(m_remote.m_process->exitCode(), QProcess::NormalExit); +// } else if (status == QSsh::SshRemoteProcess::CrashExit) { +// m_remote.m_error = QProcess::Crashed; +// emit finished(m_remote.m_process->exitCode(), QProcess::CrashExit); +// } + emit finished(0, QProcess::NormalExit); } } // namespace Valgrind diff --git a/src/plugins/valgrind/valgrindprocess.h b/src/plugins/valgrind/valgrindprocess.h index b85214e09543c8a84c54616d4fadd62d6fda1540..50182eb1a2e6c66c41480c9da7d89550e59c62df 100644 --- a/src/plugins/valgrind/valgrindprocess.h +++ b/src/plugins/valgrind/valgrindprocess.h @@ -66,7 +66,6 @@ public: ProjectExplorer::IDevice::ConstPtr device() const { return m_device; } qint64 pid() const; - QSsh::SshConnection *connection() const; bool isLocal() const; signals: @@ -74,33 +73,24 @@ signals: void finished(int, QProcess::ExitStatus); void error(QProcess::ProcessError); void processOutput(const QString &, Utils::OutputFormat format); - void localHostAddressRetrieved(const QHostAddress &localHostAddress); private: - void handleRemoteStderr(); - void handleRemoteStdout(); - void handleError(QSsh::SshError); + void handleRemoteStderr(const QByteArray &b); + void handleRemoteStdout(const QByteArray &b); - void closed(int); - void connected(); + void closed(bool success); void localProcessStarted(); void remoteProcessStarted(); - void findPIDOutputReceived(); + void findPIDOutputReceived(const QByteArray &out); QString argumentString(Utils::OsType osType) const; ProjectExplorer::StandardRunnable m_debuggee; - ProjectExplorer::ApplicationLauncher m_localProcess; - qint64 m_pid; + ProjectExplorer::ApplicationLauncher m_valgrindProcess; + qint64 m_pid = 0; ProjectExplorer::IDevice::ConstPtr m_device; - struct Remote { - QSsh::SshConnection *m_connection; - QSsh::SshRemoteProcess::Ptr m_process; - QString m_errorString; - QProcess::ProcessError m_error; - QSsh::SshRemoteProcess::Ptr m_findPID; - } m_remote; + ProjectExplorer::ApplicationLauncher m_findPID; QSsh::SshConnectionParameters m_params; QString m_valgrindExecutable; diff --git a/src/plugins/valgrind/valgrindrunner.cpp b/src/plugins/valgrind/valgrindrunner.cpp index 5f348cb3536ef6bd79bba09f5d1ce4dbee8433f4..e85a872aef8d998150c1e5e792c3921cb979d01f 100644 --- a/src/plugins/valgrind/valgrindrunner.cpp +++ b/src/plugins/valgrind/valgrindrunner.cpp @@ -39,6 +39,7 @@ #include <ssh/sshremoteprocess.h> #include <QEventLoop> +#include <QNetworkInterface> #include <QTcpServer> #include <QTcpSocket> @@ -49,6 +50,7 @@ namespace Valgrind { class ValgrindRunner::Private { public: + QHostAddress localServerAddress; ValgrindProcess *process = nullptr; QProcess::ProcessChannelMode channelMode = QProcess::SeparateChannels; bool finished = false; @@ -125,6 +127,11 @@ void ValgrindRunner::setProcessChannelMode(QProcess::ProcessChannelMode mode) d->channelMode = mode; } +void ValgrindRunner::setLocalServerAddress(const QHostAddress &localServerAddress) +{ + d->localServerAddress = localServerAddress; +} + void ValgrindRunner::setDevice(const IDevice::ConstPtr &device) { d->device = device; @@ -152,10 +159,8 @@ void ValgrindRunner::setToolName(const QString &toolName) bool ValgrindRunner::start() { - // FIXME: Remove hack. - if (d->tool == "memcheck" - && device()->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) { - if (!startServers(QHostAddress::LocalHost)) + if (!d->localServerAddress.isNull()) { + if (!startServers()) return false; setValgrindArguments(memcheckLogArguments() + valgrindArguments()); } @@ -176,8 +181,6 @@ bool ValgrindRunner::start() this, &ValgrindRunner::processFinished); QObject::connect(d->process, &ValgrindProcess::error, this, &ValgrindRunner::processError); - QObject::connect(d->process, &ValgrindProcess::localHostAddressRetrieved, - this, &ValgrindRunner::localHostAddressRetrieved); d->process->run(d->debuggee.runMode); @@ -214,14 +217,6 @@ void ValgrindRunner::processFinished(int ret, QProcess::ExitStatus status) emit processErrorReceived(errorString(), d->process->processError()); } -void ValgrindRunner::localHostAddressRetrieved(const QHostAddress &localHostAddress) -{ - if (startServers(localHostAddress)) { - setValgrindArguments(memcheckLogArguments() + valgrindArguments()); - valgrindProcess()->setValgrindArguments(fullValgrindArguments()); - } -} - QString ValgrindRunner::errorString() const { return d->process ? d->process->errorString() : QString(); @@ -274,10 +269,10 @@ void ValgrindRunner::readLogSocket() emit logMessageReceived(d->logSocket->readAll()); } -bool ValgrindRunner::startServers(const QHostAddress &localHostAddress) +bool ValgrindRunner::startServers() { - bool check = d->xmlServer.listen(localHostAddress); - const QString ip = localHostAddress.toString(); + bool check = d->xmlServer.listen(d->localServerAddress); + const QString ip = d->localServerAddress.toString(); if (!check) { emit processErrorReceived(tr("XmlServer on %1:").arg(ip) + ' ' + d->xmlServer.errorString(), QProcess::FailedToStart ); @@ -286,7 +281,7 @@ bool ValgrindRunner::startServers(const QHostAddress &localHostAddress) d->xmlServer.setMaxPendingConnections(1); connect(&d->xmlServer, &QTcpServer::newConnection, this, &ValgrindRunner::xmlSocketConnected); - check = d->logServer.listen(localHostAddress); + check = d->logServer.listen(d->localServerAddress); if (!check) { emit processErrorReceived(tr("LogServer on %1:").arg(ip) + ' ' + d->logServer.errorString(), QProcess::FailedToStart ); @@ -298,16 +293,33 @@ bool ValgrindRunner::startServers(const QHostAddress &localHostAddress) return true; } +static void handleSocketParameter(const QString &prefix, const QTcpServer &tcpServer, + bool *useXml, QStringList *arguments) +{ + QHostAddress serverAddress = tcpServer.serverAddress(); + if (serverAddress.protocol() != QAbstractSocket::IPv4Protocol) { + // Report will end up in the Application Output pane, i.e. not have + // clickable items, but that's better than nothing. + qWarning("Need IPv4 for valgrind"); + *useXml = false; + } else { + *arguments << QString("%1=%2:%3").arg(prefix).arg(serverAddress.toString()) + .arg(tcpServer.serverPort()); + } +} + QStringList ValgrindRunner::memcheckLogArguments() const { - QStringList arguments; - if (!d->disableXml) - arguments << QLatin1String("--xml=yes"); - arguments << QString::fromLatin1("--xml-socket=%1:%2") - .arg(d->xmlServer.serverAddress().toString()).arg(d->xmlServer.serverPort()) - << QLatin1String("--child-silent-after-fork=yes") - << QString::fromLatin1("--log-socket=%1:%2") - .arg(d->logServer.serverAddress().toString()).arg(d->logServer.serverPort()); + bool enableXml = !d->disableXml; + + QStringList arguments = {"--child-silent-after-fork=yes"}; + + handleSocketParameter("--xml-socket", d->xmlServer, &enableXml, &arguments); + handleSocketParameter("--log-socket", d->logServer, &enableXml, &arguments); + + if (enableXml) + arguments << "--xml=yes"; + return arguments; } diff --git a/src/plugins/valgrind/valgrindrunner.h b/src/plugins/valgrind/valgrindrunner.h index 9732d0935674ecbed53c8c7384559e526ce53442..371ec7d5790f8d63a36112e76718e35b4d3d75f6 100644 --- a/src/plugins/valgrind/valgrindrunner.h +++ b/src/plugins/valgrind/valgrindrunner.h @@ -56,6 +56,7 @@ public: void setValgrindArguments(const QStringList &toolArguments); void setDebuggee(const ProjectExplorer::StandardRunnable &debuggee) ; void setProcessChannelMode(QProcess::ProcessChannelMode mode); + void setLocalServerAddress(const QHostAddress &localServerAddress); void setDevice(const ProjectExplorer::IDevice::ConstPtr &device); ProjectExplorer::IDevice::ConstPtr device() const; @@ -84,7 +85,7 @@ signals: void extraProcessFinished(); private: - bool startServers(const QHostAddress &localHostAddress); + bool startServers(); QStringList memcheckLogArguments() const; void processError(QProcess::ProcessError);