forked from qt-creator/qt-creator
Valgrind: Merge MemCheckRunner and ValgrindRunner base
It's mostly the xml/log handling, which can be re-used in other tools. The change is purely mechanical, including some style fixes and some modernization. Change-Id: I6b44ae71451e8d3e26df40b9af9b4ec70038a92d Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -1,7 +0,0 @@
|
||||
QT *= network
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/memcheckrunner.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/memcheckrunner.cpp
|
||||
@@ -1,179 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Author: Milian Wolff, KDAB (milian.wolff@kdab.com)
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "memcheckrunner.h"
|
||||
|
||||
#include "../xmlprotocol/error.h"
|
||||
#include "../xmlprotocol/status.h"
|
||||
#include "../xmlprotocol/threadedparser.h"
|
||||
#include "../valgrindprocess.h"
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QNetworkInterface>
|
||||
#include <QTcpServer>
|
||||
#include <QTcpSocket>
|
||||
#include <QEventLoop>
|
||||
#include <QApplication>
|
||||
#include <QDialog>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QLabel>
|
||||
#include <QListWidget>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Memcheck {
|
||||
|
||||
class MemcheckRunner::Private
|
||||
{
|
||||
public:
|
||||
explicit Private()
|
||||
: parser(0),
|
||||
logSocket(0),
|
||||
disableXml(false)
|
||||
{
|
||||
}
|
||||
|
||||
QTcpServer xmlServer;
|
||||
XmlProtocol::ThreadedParser *parser;
|
||||
QTcpServer logServer;
|
||||
QTcpSocket *logSocket;
|
||||
bool disableXml;
|
||||
};
|
||||
|
||||
MemcheckRunner::MemcheckRunner(QObject *parent)
|
||||
: ValgrindRunner(parent),
|
||||
d(new Private)
|
||||
{
|
||||
setToolName("memcheck");
|
||||
}
|
||||
|
||||
MemcheckRunner::~MemcheckRunner()
|
||||
{
|
||||
if (d->parser->isRunning()) {
|
||||
// make sure we don't delete the thread while it's still running
|
||||
waitForFinished();
|
||||
}
|
||||
delete d;
|
||||
d = 0;
|
||||
}
|
||||
|
||||
void MemcheckRunner::setParser(XmlProtocol::ThreadedParser *parser)
|
||||
{
|
||||
QTC_ASSERT(!d->parser, qt_noop());
|
||||
d->parser = parser;
|
||||
}
|
||||
|
||||
bool MemcheckRunner::start()
|
||||
{
|
||||
QTC_ASSERT(d->parser, return false);
|
||||
|
||||
if (device()->type() == ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE) {
|
||||
if (!startServers(QHostAddress::LocalHost))
|
||||
return false;
|
||||
setValgrindArguments(memcheckLogArguments() + valgrindArguments());
|
||||
}
|
||||
|
||||
return ValgrindRunner::start();
|
||||
}
|
||||
|
||||
// Workaround for valgrind bug when running vgdb with xml output
|
||||
// https://bugs.kde.org/show_bug.cgi?id=343902
|
||||
void MemcheckRunner::disableXml()
|
||||
{
|
||||
d->disableXml = true;
|
||||
}
|
||||
|
||||
void MemcheckRunner::xmlSocketConnected()
|
||||
{
|
||||
QTcpSocket *socket = d->xmlServer.nextPendingConnection();
|
||||
QTC_ASSERT(socket, return);
|
||||
d->xmlServer.close();
|
||||
d->parser->parse(socket);
|
||||
}
|
||||
|
||||
void MemcheckRunner::logSocketConnected()
|
||||
{
|
||||
d->logSocket = d->logServer.nextPendingConnection();
|
||||
QTC_ASSERT(d->logSocket, return);
|
||||
connect(d->logSocket, &QIODevice::readyRead,
|
||||
this, &MemcheckRunner::readLogSocket);
|
||||
d->logServer.close();
|
||||
}
|
||||
|
||||
void MemcheckRunner::readLogSocket()
|
||||
{
|
||||
QTC_ASSERT(d->logSocket, return);
|
||||
emit logMessageReceived(d->logSocket->readAll());
|
||||
}
|
||||
|
||||
bool MemcheckRunner::startServers(const QHostAddress &localHostAddress)
|
||||
{
|
||||
bool check = d->xmlServer.listen(localHostAddress);
|
||||
const QString ip = localHostAddress.toString();
|
||||
if (!check) {
|
||||
emit processErrorReceived( tr("XmlServer on %1:").arg(ip) + QLatin1Char(' ')
|
||||
+ d->xmlServer.errorString(), QProcess::FailedToStart );
|
||||
return false;
|
||||
}
|
||||
d->xmlServer.setMaxPendingConnections(1);
|
||||
connect(&d->xmlServer, &QTcpServer::newConnection,
|
||||
this, &MemcheckRunner::xmlSocketConnected);
|
||||
check = d->logServer.listen(localHostAddress);
|
||||
if (!check) {
|
||||
emit processErrorReceived( tr("LogServer on %1:").arg(ip) + QLatin1Char(' ')
|
||||
+ d->logServer.errorString(), QProcess::FailedToStart );
|
||||
return false;
|
||||
}
|
||||
d->logServer.setMaxPendingConnections(1);
|
||||
connect(&d->logServer, &QTcpServer::newConnection,
|
||||
this, &MemcheckRunner::logSocketConnected);
|
||||
return true;
|
||||
}
|
||||
|
||||
QStringList MemcheckRunner::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());
|
||||
return arguments;
|
||||
}
|
||||
|
||||
void MemcheckRunner::localHostAddressRetrieved(const QHostAddress &localHostAddress)
|
||||
{
|
||||
if (startServers(localHostAddress)) {
|
||||
setValgrindArguments(memcheckLogArguments() + valgrindArguments());
|
||||
valgrindProcess()->setValgrindArguments(fullValgrindArguments());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Memcheck
|
||||
} // namespace Valgrind
|
||||
@@ -1,69 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Author: Milian Wolff, KDAB (milian.wolff@kdab.com)
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../valgrindrunner.h"
|
||||
|
||||
namespace Valgrind {
|
||||
|
||||
namespace XmlProtocol{
|
||||
class ThreadedParser;
|
||||
}
|
||||
|
||||
namespace Memcheck {
|
||||
|
||||
class MemcheckRunner : public ValgrindRunner
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MemcheckRunner(QObject *parent = 0);
|
||||
~MemcheckRunner();
|
||||
|
||||
void setParser(XmlProtocol::ThreadedParser *parser);
|
||||
bool start() override;
|
||||
void disableXml();
|
||||
|
||||
signals:
|
||||
void logMessageReceived(const QByteArray &);
|
||||
|
||||
private:
|
||||
void localHostAddressRetrieved(const QHostAddress &localHostAddress) override;
|
||||
|
||||
void xmlSocketConnected();
|
||||
void logSocketConnected();
|
||||
void readLogSocket();
|
||||
|
||||
bool startServers(const QHostAddress &localHostAddress);
|
||||
QStringList memcheckLogArguments() const;
|
||||
|
||||
class Private;
|
||||
Private *d;
|
||||
};
|
||||
|
||||
} // namespace Memcheck
|
||||
} // namespace Valgrind
|
||||
@@ -61,9 +61,9 @@ MemcheckToolRunner::MemcheckToolRunner(RunControl *runControl, bool withGdb)
|
||||
this, &MemcheckToolRunner::suppressionCount);
|
||||
|
||||
if (withGdb) {
|
||||
connect(&m_runner, &Memcheck::MemcheckRunner::started,
|
||||
connect(&m_runner, &ValgrindRunner::started,
|
||||
this, &MemcheckToolRunner::startDebugger);
|
||||
connect(&m_runner, &Memcheck::MemcheckRunner::logMessageReceived,
|
||||
connect(&m_runner, &ValgrindRunner::logMessageReceived,
|
||||
this, &MemcheckToolRunner::appendLog);
|
||||
m_runner.disableXml();
|
||||
} else {
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#include "valgrindengine.h"
|
||||
|
||||
#include "memcheck/memcheckrunner.h"
|
||||
#include "valgrindrunner.h"
|
||||
#include "xmlprotocol/threadedparser.h"
|
||||
|
||||
namespace Valgrind {
|
||||
@@ -61,7 +61,7 @@ private:
|
||||
void appendLog(const QByteArray &data);
|
||||
|
||||
XmlProtocol::ThreadedParser m_parser;
|
||||
Memcheck::MemcheckRunner m_runner;
|
||||
ValgrindRunner m_runner;
|
||||
const bool m_withGdb;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
include(../../qtcreatorplugin.pri)
|
||||
include(callgrind/callgrind.pri)
|
||||
include(memcheck/memcheck.pri)
|
||||
include(xmlprotocol/xmlprotocol.pri)
|
||||
QT *= network
|
||||
|
||||
|
||||
@@ -62,15 +62,6 @@ QtcPlugin {
|
||||
]
|
||||
}
|
||||
|
||||
Group {
|
||||
name: "Memcheck"
|
||||
prefix: "memcheck/"
|
||||
files: [
|
||||
"memcheckrunner.cpp",
|
||||
"memcheckrunner.h"
|
||||
]
|
||||
}
|
||||
|
||||
Group {
|
||||
name: "XML Protocol"
|
||||
prefix: "xmlprotocol/"
|
||||
|
||||
@@ -27,7 +27,6 @@ HEADERS += \
|
||||
$$PWD/callgrind/callgrindcycledetection.h \
|
||||
$$PWD/callgrind/callgrindproxymodel.h \
|
||||
$$PWD/callgrind/callgrindstackbrowser.h \
|
||||
$$PWD/memcheck/memcheckrunner.h \
|
||||
$$PWD/valgrindrunner.h \
|
||||
$$PWD/valgrindprocess.h
|
||||
|
||||
@@ -54,7 +53,6 @@ SOURCES += $$PWD/xmlprotocol/error.cpp \
|
||||
$$PWD/callgrind/callgrindcycledetection.cpp \
|
||||
$$PWD/callgrind/callgrindproxymodel.cpp \
|
||||
$$PWD/callgrind/callgrindstackbrowser.cpp \
|
||||
$$PWD/memcheck/memcheckrunner.cpp \
|
||||
$$PWD/valgrindrunner.cpp \
|
||||
$$PWD/valgrindprocess.cpp
|
||||
|
||||
|
||||
@@ -115,9 +115,6 @@ void ValgrindMemcheckParserTest::initTestCase()
|
||||
{
|
||||
m_server = new QTcpServer(this);
|
||||
QVERIFY(m_server->listen());
|
||||
|
||||
m_socket = 0;
|
||||
m_process = 0;
|
||||
}
|
||||
|
||||
void ValgrindMemcheckParserTest::initTest(const QString &testfile, const QStringList &otherArgs)
|
||||
@@ -459,21 +456,19 @@ void ValgrindMemcheckParserTest::testValgrindGarbage()
|
||||
void ValgrindMemcheckParserTest::testParserStop()
|
||||
{
|
||||
ThreadedParser parser;
|
||||
Memcheck::MemcheckRunner runner;
|
||||
ValgrindRunner runner;
|
||||
runner.setValgrindExecutable(fakeValgrindExecutable());
|
||||
runner.setParser(&parser);
|
||||
runner.setValgrindArguments(QStringList({ "-i", dataFile("memcheck-output-sample1.xml"),
|
||||
"--wait", "5" }));
|
||||
runner.setValgrindArguments({"-i", dataFile("memcheck-output-sample1.xml"), "--wait", "5" });
|
||||
runner.setProcessChannelMode(QProcess::ForwardedChannels);
|
||||
|
||||
runner.setDevice(ProjectExplorer::DeviceManager::instance()->defaultDevice(
|
||||
Core::Id(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)));
|
||||
ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE));
|
||||
runner.start();
|
||||
QTest::qWait(500);
|
||||
runner.stop();
|
||||
}
|
||||
|
||||
|
||||
void ValgrindMemcheckParserTest::testRealValgrind()
|
||||
{
|
||||
const Utils::Environment &sysEnv = Utils::Environment::systemEnvironment();
|
||||
@@ -487,11 +482,11 @@ void ValgrindMemcheckParserTest::testRealValgrind()
|
||||
ProjectExplorer::StandardRunnable debuggee;
|
||||
debuggee.executable = executable;
|
||||
debuggee.environment = sysEnv;
|
||||
Memcheck::MemcheckRunner runner;
|
||||
ValgrindRunner runner;
|
||||
runner.setValgrindExecutable("valgrind");
|
||||
runner.setDebuggee(debuggee);
|
||||
runner.setDevice(ProjectExplorer::DeviceManager::instance()->defaultDevice(
|
||||
Core::Id(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)));
|
||||
ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE));
|
||||
runner.setParser(&parser);
|
||||
RunnerDumper dumper(&runner, &parser);
|
||||
runner.start();
|
||||
@@ -529,13 +524,13 @@ void ValgrindMemcheckParserTest::testValgrindStartError()
|
||||
debuggeeExecutable.environment = Utils::Environment::systemEnvironment();
|
||||
debuggeeExecutable.commandLineArguments = debuggeeArgs;
|
||||
|
||||
Memcheck::MemcheckRunner runner;
|
||||
ValgrindRunner runner;
|
||||
runner.setParser(&parser);
|
||||
runner.setValgrindExecutable(valgrindExe);
|
||||
runner.setValgrindArguments(valgrindArgs);
|
||||
runner.setDebuggee(debuggeeExecutable);
|
||||
runner.setDevice(ProjectExplorer::DeviceManager::instance()->defaultDevice(
|
||||
Core::Id(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)));
|
||||
ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE));
|
||||
RunnerDumper dumper(&runner, &parser);
|
||||
runner.start();
|
||||
runner.waitForFinished();
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
#include "xmlprotocol/status.h"
|
||||
#include "xmlprotocol/threadedparser.h"
|
||||
#include "xmlprotocol/parser.h"
|
||||
#include "memcheck/memcheckrunner.h"
|
||||
#include "valgrindrunner.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QTcpServer;
|
||||
@@ -44,7 +44,6 @@ class QTcpSocket;
|
||||
class QProcess;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Test {
|
||||
|
||||
@@ -92,19 +91,17 @@ class RunnerDumper : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RunnerDumper(Valgrind::Memcheck::MemcheckRunner *runner, Valgrind::XmlProtocol::ThreadedParser *parser)
|
||||
: QObject()
|
||||
, m_errorReceived(false)
|
||||
explicit RunnerDumper(ValgrindRunner *runner, XmlProtocol::ThreadedParser *parser)
|
||||
{
|
||||
connect(parser, &Valgrind::XmlProtocol::ThreadedParser::error,
|
||||
connect(parser, &XmlProtocol::ThreadedParser::error,
|
||||
this, &RunnerDumper::error);
|
||||
connect(parser, &Valgrind::XmlProtocol::ThreadedParser::internalError,
|
||||
connect(parser, &XmlProtocol::ThreadedParser::internalError,
|
||||
this, &RunnerDumper::internalError);
|
||||
connect(parser, &Valgrind::XmlProtocol::ThreadedParser::status,
|
||||
connect(parser, &XmlProtocol::ThreadedParser::status,
|
||||
this, &RunnerDumper::status);
|
||||
connect(runner, &Valgrind::Memcheck::MemcheckRunner::logMessageReceived,
|
||||
connect(runner, &ValgrindRunner::logMessageReceived,
|
||||
this, &RunnerDumper::logMessageReceived);
|
||||
connect(runner, &Valgrind::ValgrindRunner::processErrorReceived,
|
||||
connect(runner, &ValgrindRunner::processErrorReceived,
|
||||
this, &RunnerDumper::processErrorReceived);
|
||||
}
|
||||
|
||||
@@ -133,15 +130,14 @@ public:
|
||||
}
|
||||
|
||||
public:
|
||||
bool m_errorReceived;
|
||||
|
||||
bool m_errorReceived = false;
|
||||
};
|
||||
|
||||
class ValgrindMemcheckParserTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
private slots:
|
||||
void initTestCase();
|
||||
void cleanup();
|
||||
|
||||
@@ -162,9 +158,9 @@ private Q_SLOTS:
|
||||
private:
|
||||
void initTest(const QString &testfile, const QStringList &otherArgs = QStringList());
|
||||
|
||||
QTcpServer *m_server = 0;
|
||||
QProcess *m_process = 0;
|
||||
QTcpSocket *m_socket = 0;
|
||||
QTcpServer *m_server = nullptr;
|
||||
QProcess *m_process = nullptr;
|
||||
QTcpSocket *m_socket = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Test
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#include "valgrindrunner.h"
|
||||
#include "valgrindprocess.h"
|
||||
|
||||
#include "xmlprotocol/threadedparser.h"
|
||||
|
||||
#include <projectexplorer/runnables.h>
|
||||
|
||||
#include <utils/environment.h>
|
||||
@@ -37,6 +39,8 @@
|
||||
#include <ssh/sshremoteprocess.h>
|
||||
|
||||
#include <QEventLoop>
|
||||
#include <QTcpServer>
|
||||
#include <QTcpSocket>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
@@ -45,7 +49,7 @@ namespace Valgrind {
|
||||
class ValgrindRunner::Private
|
||||
{
|
||||
public:
|
||||
ValgrindProcess *process = 0;
|
||||
ValgrindProcess *process = nullptr;
|
||||
QProcess::ProcessChannelMode channelMode = QProcess::SeparateChannels;
|
||||
bool finished = false;
|
||||
QString valgrindExecutable;
|
||||
@@ -53,11 +57,18 @@ public:
|
||||
StandardRunnable debuggee;
|
||||
IDevice::ConstPtr device;
|
||||
QString tool;
|
||||
|
||||
QTcpServer xmlServer;
|
||||
XmlProtocol::ThreadedParser *parser = nullptr;
|
||||
QTcpServer logServer;
|
||||
QTcpSocket *logSocket = nullptr;
|
||||
bool disableXml = false;
|
||||
};
|
||||
|
||||
ValgrindRunner::ValgrindRunner(QObject *parent)
|
||||
: QObject(parent), d(new Private)
|
||||
{
|
||||
setToolName("memcheck");
|
||||
}
|
||||
|
||||
ValgrindRunner::~ValgrindRunner()
|
||||
@@ -66,6 +77,10 @@ ValgrindRunner::~ValgrindRunner()
|
||||
// make sure we don't delete the thread while it's still running
|
||||
waitForFinished();
|
||||
}
|
||||
if (d->parser->isRunning()) {
|
||||
// make sure we don't delete the thread while it's still running
|
||||
waitForFinished();
|
||||
}
|
||||
delete d;
|
||||
d = 0;
|
||||
}
|
||||
@@ -137,6 +152,14 @@ 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))
|
||||
return false;
|
||||
setValgrindArguments(memcheckLogArguments() + valgrindArguments());
|
||||
}
|
||||
|
||||
d->process = new ValgrindProcess(d->device, this);
|
||||
d->process->setProcessChannelMode(d->channelMode);
|
||||
// consider appending our options last so they override any interfering user-supplied options
|
||||
@@ -193,15 +216,15 @@ void ValgrindRunner::processFinished(int ret, QProcess::ExitStatus status)
|
||||
|
||||
void ValgrindRunner::localHostAddressRetrieved(const QHostAddress &localHostAddress)
|
||||
{
|
||||
Q_UNUSED(localHostAddress);
|
||||
if (startServers(localHostAddress)) {
|
||||
setValgrindArguments(memcheckLogArguments() + valgrindArguments());
|
||||
valgrindProcess()->setValgrindArguments(fullValgrindArguments());
|
||||
}
|
||||
}
|
||||
|
||||
QString ValgrindRunner::errorString() const
|
||||
{
|
||||
if (d->process)
|
||||
return d->process->errorString();
|
||||
else
|
||||
return QString();
|
||||
return d->process ? d->process->errorString() : QString();
|
||||
}
|
||||
|
||||
void ValgrindRunner::stop()
|
||||
@@ -215,4 +238,78 @@ ValgrindProcess *ValgrindRunner::valgrindProcess() const
|
||||
return d->process;
|
||||
}
|
||||
|
||||
void ValgrindRunner::setParser(XmlProtocol::ThreadedParser *parser)
|
||||
{
|
||||
QTC_ASSERT(!d->parser, qt_noop());
|
||||
d->parser = parser;
|
||||
}
|
||||
|
||||
|
||||
// Workaround for valgrind bug when running vgdb with xml output
|
||||
// https://bugs.kde.org/show_bug.cgi?id=343902
|
||||
void ValgrindRunner::disableXml()
|
||||
{
|
||||
d->disableXml = true;
|
||||
}
|
||||
|
||||
void ValgrindRunner::xmlSocketConnected()
|
||||
{
|
||||
QTcpSocket *socket = d->xmlServer.nextPendingConnection();
|
||||
QTC_ASSERT(socket, return);
|
||||
d->xmlServer.close();
|
||||
d->parser->parse(socket);
|
||||
}
|
||||
|
||||
void ValgrindRunner::logSocketConnected()
|
||||
{
|
||||
d->logSocket = d->logServer.nextPendingConnection();
|
||||
QTC_ASSERT(d->logSocket, return);
|
||||
connect(d->logSocket, &QIODevice::readyRead,
|
||||
this, &ValgrindRunner::readLogSocket);
|
||||
d->logServer.close();
|
||||
}
|
||||
|
||||
void ValgrindRunner::readLogSocket()
|
||||
{
|
||||
QTC_ASSERT(d->logSocket, return);
|
||||
emit logMessageReceived(d->logSocket->readAll());
|
||||
}
|
||||
|
||||
bool ValgrindRunner::startServers(const QHostAddress &localHostAddress)
|
||||
{
|
||||
bool check = d->xmlServer.listen(localHostAddress);
|
||||
const QString ip = localHostAddress.toString();
|
||||
if (!check) {
|
||||
emit processErrorReceived(tr("XmlServer on %1:").arg(ip) + ' '
|
||||
+ d->xmlServer.errorString(), QProcess::FailedToStart );
|
||||
return false;
|
||||
}
|
||||
d->xmlServer.setMaxPendingConnections(1);
|
||||
connect(&d->xmlServer, &QTcpServer::newConnection,
|
||||
this, &ValgrindRunner::xmlSocketConnected);
|
||||
check = d->logServer.listen(localHostAddress);
|
||||
if (!check) {
|
||||
emit processErrorReceived(tr("LogServer on %1:").arg(ip) + ' '
|
||||
+ d->logServer.errorString(), QProcess::FailedToStart );
|
||||
return false;
|
||||
}
|
||||
d->logServer.setMaxPendingConnections(1);
|
||||
connect(&d->logServer, &QTcpServer::newConnection,
|
||||
this, &ValgrindRunner::logSocketConnected);
|
||||
return true;
|
||||
}
|
||||
|
||||
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());
|
||||
return arguments;
|
||||
}
|
||||
|
||||
} // namespace Valgrind
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
|
||||
namespace Valgrind {
|
||||
|
||||
namespace XmlProtocol { class ThreadedParser; }
|
||||
|
||||
class ValgrindProcess;
|
||||
|
||||
class ValgrindRunner : public QObject
|
||||
@@ -63,12 +65,16 @@ public:
|
||||
|
||||
QString errorString() const;
|
||||
|
||||
virtual bool start();
|
||||
bool start();
|
||||
void stop();
|
||||
|
||||
ValgrindProcess *valgrindProcess() const;
|
||||
|
||||
void setParser(XmlProtocol::ThreadedParser *parser);
|
||||
void disableXml();
|
||||
|
||||
signals:
|
||||
void logMessageReceived(const QByteArray &);
|
||||
void extraStart();
|
||||
|
||||
void processOutputReceived(const QString &, Utils::OutputFormat);
|
||||
@@ -77,12 +83,18 @@ signals:
|
||||
void finished();
|
||||
void extraProcessFinished();
|
||||
|
||||
protected:
|
||||
virtual void processError(QProcess::ProcessError);
|
||||
virtual void processFinished(int, QProcess::ExitStatus);
|
||||
virtual void localHostAddressRetrieved(const QHostAddress &localHostAddress);
|
||||
|
||||
private:
|
||||
bool startServers(const QHostAddress &localHostAddress);
|
||||
QStringList memcheckLogArguments() const;
|
||||
|
||||
void processError(QProcess::ProcessError);
|
||||
void processFinished(int, QProcess::ExitStatus);
|
||||
|
||||
void localHostAddressRetrieved(const QHostAddress &localHostAddress);
|
||||
void xmlSocketConnected();
|
||||
void logSocketConnected();
|
||||
void readLogSocket();
|
||||
|
||||
class Private;
|
||||
Private *d;
|
||||
};
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "xmlprotocol/suppression.h"
|
||||
#include "xmlprotocol/threadedparser.h"
|
||||
#include "xmlprotocol/parser.h"
|
||||
#include "memcheck/memcheckrunner.h"
|
||||
#include "valgrindrunner.h"
|
||||
|
||||
#include <projectexplorer/devicesupport/devicemanager.h>
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
@@ -45,7 +45,6 @@
|
||||
#define HEADER_LENGTH 25
|
||||
|
||||
using namespace Valgrind::XmlProtocol;
|
||||
using namespace Valgrind::Memcheck;
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Test {
|
||||
@@ -131,10 +130,10 @@ void ValgrindTestRunnerTest::init()
|
||||
Q_ASSERT(m_logMessages.isEmpty());
|
||||
|
||||
Q_ASSERT(!m_runner);
|
||||
m_runner = new MemcheckRunner;
|
||||
m_runner->setValgrindExecutable(QLatin1String("valgrind"));
|
||||
m_runner = new ValgrindRunner;
|
||||
m_runner->setValgrindExecutable("valgrind");
|
||||
m_runner->setProcessChannelMode(QProcess::ForwardedChannels);
|
||||
connect(m_runner, &MemcheckRunner::logMessageReceived,
|
||||
connect(m_runner, &ValgrindRunner::logMessageReceived,
|
||||
this, &ValgrindTestRunnerTest::logMessageReceived);
|
||||
connect(m_runner, &ValgrindRunner::processErrorReceived,
|
||||
this, &ValgrindTestRunnerTest::internalError);
|
||||
|
||||
@@ -26,20 +26,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xmlprotocol/error.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
|
||||
#include "xmlprotocol/error.h"
|
||||
|
||||
namespace Valgrind {
|
||||
|
||||
namespace XmlProtocol {
|
||||
class ThreadedParser;
|
||||
}
|
||||
|
||||
namespace Memcheck {
|
||||
class MemcheckRunner;
|
||||
}
|
||||
namespace XmlProtocol { class ThreadedParser; }
|
||||
class ValgrindRunner;
|
||||
|
||||
namespace Test {
|
||||
|
||||
@@ -77,8 +72,8 @@ private slots:
|
||||
private:
|
||||
QString runTestBinary(const QString &binary, const QStringList &vArgs = QStringList());
|
||||
|
||||
XmlProtocol::ThreadedParser *m_parser = 0;
|
||||
Memcheck::MemcheckRunner *m_runner = 0;
|
||||
XmlProtocol::ThreadedParser *m_parser = nullptr;
|
||||
ValgrindRunner *m_runner = nullptr;
|
||||
QList<QByteArray> m_logMessages;
|
||||
QList<XmlProtocol::Error> m_errors;
|
||||
bool m_expectCrash = false;
|
||||
|
||||
@@ -55,7 +55,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
ThreadedParser parser;
|
||||
|
||||
Memcheck::MemcheckRunner runner;
|
||||
ValgrindRunner runner;
|
||||
runner.setValgrindExecutable(fakeValgrindExecutable());
|
||||
runner.setValgrindArguments(QStringList() << QLatin1String("-i") << dataFile(QLatin1String("memcheck-output-sample1.xml")) );
|
||||
runner.setParser(&parser);
|
||||
|
||||
@@ -34,13 +34,13 @@
|
||||
#include <valgrind/xmlprotocol/error.h>
|
||||
#include <valgrind/xmlprotocol/errorlistmodel.h>
|
||||
#include <valgrind/xmlprotocol/stackmodel.h>
|
||||
#include <valgrind/memcheck/memcheckrunner.h>
|
||||
#include <valgrind/valgrindrunner.h>
|
||||
|
||||
class ModelDemo : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ModelDemo(Valgrind::Memcheck::MemcheckRunner *r, QObject *parent = 0)
|
||||
explicit ModelDemo(Valgrind::ValgrindRunner *r, QObject *parent = 0)
|
||||
: QObject(parent)
|
||||
, runner(r)
|
||||
{
|
||||
@@ -64,5 +64,5 @@ public Q_SLOTS:
|
||||
|
||||
|
||||
private:
|
||||
Valgrind::Memcheck::MemcheckRunner *runner;
|
||||
Valgrind::ValgrindRunner *runner;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user