Commit 1614d6b6 authored by hjk's avatar hjk
Browse files

debugger: small refactoring of the access to the gdb process in the gdbengine

That's the first step to make the gdb/trk Adapter work with the otherwise
unmodified gdb engine. GdbProcessBase is inherited by GdbProcess and the
gdb/trk Adapter. In the GdbProcess case it's just a wrapper around a QProcess
running gdb, in the Adapter case it's the interface to the gdb process in the
whole rfomm/gdb/gdbserver combo.
parent 5d26f533
......@@ -144,7 +144,7 @@ static QByteArray parsePlainConsoleStream(const GdbResultRecord &record)
//
///////////////////////////////////////////////////////////////////////
GdbEngine::GdbEngine(DebuggerManager *parent) :
GdbEngine::GdbEngine(DebuggerManager *parent, GdbProcessBase *gdbProc) :
#ifdef Q_OS_WIN // Do injection loading with MinGW (call loading does not work with 64bit)
m_dumperInjectionLoad(true),
#else
......@@ -153,6 +153,7 @@ GdbEngine::GdbEngine(DebuggerManager *parent) :
q(parent),
qq(parent->engineInterface())
{
m_gdbProc = gdbProc;
m_stubProc.setMode(Core::Utils::ConsoleProcess::Debug);
#ifdef Q_OS_UNIX
m_stubProc.setSettings(Core::ICore::instance()->settings());
......@@ -164,19 +165,20 @@ GdbEngine::GdbEngine(DebuggerManager *parent) :
GdbEngine::~GdbEngine()
{
// prevent sending error messages afterwards
m_gdbProc.disconnect(this);
m_gdbProc->disconnect(this);
delete m_gdbProc;
}
void GdbEngine::initializeConnections()
{
// Gdb Process interaction
connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
connect(m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
this, SLOT(gdbProcError(QProcess::ProcessError)));
connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()),
connect(m_gdbProc, SIGNAL(readyReadStandardOutput()),
this, SLOT(readGdbStandardOutput()));
connect(&m_gdbProc, SIGNAL(readyReadStandardError()),
connect(m_gdbProc, SIGNAL(readyReadStandardError()),
this, SLOT(readGdbStandardError()));
connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)),
connect(m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)),
q, SLOT(exitDebugger()));
connect(&m_stubProc, SIGNAL(processError(QString)),
......@@ -614,7 +616,7 @@ void GdbEngine::stubError(const QString &msg)
void GdbEngine::readGdbStandardError()
{
qWarning() << "Unexpected gdb stderr:" << m_gdbProc.readAllStandardError();
qWarning() << "Unexpected gdb stderr:" << m_gdbProc->readAllStandardError();
}
void GdbEngine::readGdbStandardOutput()
......@@ -622,7 +624,7 @@ void GdbEngine::readGdbStandardOutput()
int newstart = 0;
int scan = m_inbuffer.size();
m_inbuffer.append(m_gdbProc.readAllStandardOutput());
m_inbuffer.append(m_gdbProc->readAllStandardOutput());
while (newstart < m_inbuffer.size()) {
int start = newstart;
......@@ -651,7 +653,7 @@ void GdbEngine::interruptInferior()
{
qq->notifyInferiorStopRequested();
if (m_gdbProc.state() == QProcess::NotRunning) {
if (m_gdbProc->state() == QProcess::NotRunning) {
debugMessage(_("TRYING TO INTERRUPT INFERIOR WITHOUT RUNNING GDB"));
qq->notifyInferiorExited();
return;
......@@ -698,7 +700,7 @@ void GdbEngine::postCommand(const QString &command, GdbCommandFlags flags,
GdbCommandCallback callback, const char *callbackName,
const QVariant &cookie)
{
if (m_gdbProc.state() == QProcess::NotRunning) {
if (m_gdbProc->state() == QProcess::NotRunning) {
debugMessage(_("NO GDB PROCESS RUNNING, CMD IGNORED: ") + command);
return;
}
......@@ -742,7 +744,7 @@ void GdbEngine::flushCommand(GdbCommand &cmd)
if (cmd.flags & EmbedToken)
cmd.command = cmd.command.arg(currentToken());
m_gdbProc.write(cmd.command.toLatin1() + "\r\n");
m_gdbProc->write(cmd.command.toLatin1() + "\r\n");
//emit gdbInputAvailable(QString(), " " + currentTime());
//emit gdbInputAvailable(QString(), "[" + currentTime() + "] " + cmd.command);
emit gdbInputAvailable(LogInput, cmd.command);
......@@ -829,12 +831,12 @@ void GdbEngine::handleResultRecord(const GdbResultRecord &record)
void GdbEngine::executeDebuggerCommand(const QString &command)
{
if (m_gdbProc.state() == QProcess::NotRunning) {
if (m_gdbProc->state() == QProcess::NotRunning) {
debugMessage(_("NO GDB PROCESS RUNNING, PLAIN CMD IGNORED: ") + command);
return;
}
m_gdbProc.write(command.toLocal8Bit() + "\r\n");
m_gdbProc->write(command.toLocal8Bit() + "\r\n");
}
void GdbEngine::handleTargetCore(const GdbResultRecord &, const QVariant &)
......@@ -1434,15 +1436,15 @@ void GdbEngine::detachDebugger()
void GdbEngine::exitDebugger()
{
debugMessage(_("GDBENGINE EXITDEBUGGER: %1").arg(m_gdbProc.state()));
if (m_gdbProc.state() == QProcess::Starting) {
debugMessage(_("GDBENGINE EXITDEBUGGER: %1").arg(m_gdbProc->state()));
if (m_gdbProc->state() == QProcess::Starting) {
debugMessage(_("WAITING FOR GDB STARTUP TO SHUTDOWN: %1")
.arg(m_gdbProc.state()));
m_gdbProc.waitForStarted();
.arg(m_gdbProc->state()));
m_gdbProc->waitForStarted();
}
if (m_gdbProc.state() == QProcess::Running) {
if (m_gdbProc->state() == QProcess::Running) {
debugMessage(_("WAITING FOR RUNNING GDB TO SHUTDOWN: %1")
.arg(m_gdbProc.state()));
.arg(m_gdbProc->state()));
if (q->status() != DebuggerInferiorStopped
&& q->status() != DebuggerProcessStartingUp) {
QTC_ASSERT(q->status() == DebuggerInferiorRunning,
......@@ -1455,17 +1457,17 @@ void GdbEngine::exitDebugger()
postCommand(_("kill"));
postCommand(_("-gdb-exit"), CB(handleExit));
// 20s can easily happen when loading webkit debug information
if (!m_gdbProc.waitForFinished(20000)) {
if (!m_gdbProc->waitForFinished(20000)) {
debugMessage(_("FORCING TERMINATION: %1")
.arg(m_gdbProc.state()));
m_gdbProc.terminate();
m_gdbProc.waitForFinished(20000);
.arg(m_gdbProc->state()));
m_gdbProc->terminate();
m_gdbProc->waitForFinished(20000);
}
}
if (m_gdbProc.state() != QProcess::NotRunning) {
if (m_gdbProc->state() != QProcess::NotRunning) {
debugMessage(_("PROBLEM STOPPING DEBUGGER: STATE %1")
.arg(m_gdbProc.state()));
m_gdbProc.kill();
.arg(m_gdbProc->state()));
m_gdbProc->kill();
}
m_outputCollector.shutdown();
......@@ -1487,9 +1489,9 @@ bool GdbEngine::startDebugger(const QSharedPointer<DebuggerStartParameters> &sp)
QStringList gdbArgs;
if (m_gdbProc.state() != QProcess::NotRunning) {
debugMessage(_("GDB IS ALREADY RUNNING, STATE: %1").arg(m_gdbProc.state()));
m_gdbProc.kill();
if (m_gdbProc->state() != QProcess::NotRunning) {
debugMessage(_("GDB IS ALREADY RUNNING, STATE: %1").arg(m_gdbProc->state()));
m_gdbProc->kill();
return false;
}
......@@ -1529,16 +1531,16 @@ bool GdbEngine::startDebugger(const QSharedPointer<DebuggerStartParameters> &sp)
gdbArgs.prepend(_("--tty=") + m_outputCollector.serverName());
if (!sp->workingDir.isEmpty())
m_gdbProc.setWorkingDirectory(sp->workingDir);
m_gdbProc->setWorkingDirectory(sp->workingDir);
if (!sp->environment.isEmpty())
m_gdbProc.setEnvironment(sp->environment);
m_gdbProc->setEnvironment(sp->environment);
}
#if 0
qDebug() << "Command:" << q->settings()->m_gdbCmd;
qDebug() << "WorkingDirectory:" << m_gdbProc.workingDirectory();
qDebug() << "WorkingDirectory:" << m_gdbProc->workingDirectory();
qDebug() << "ScriptFile:" << q->settings()->m_scriptFile;
qDebug() << "Environment:" << m_gdbProc.environment();
qDebug() << "Environment:" << m_gdbProc->environment();
qDebug() << "Arguments:" << gdbArgs;
qDebug() << "BuildDir:" << sp->buildDir;
qDebug() << "ExeFile:" << sp->executable;
......@@ -1546,10 +1548,10 @@ bool GdbEngine::startDebugger(const QSharedPointer<DebuggerStartParameters> &sp)
QString loc = theDebuggerStringSetting(GdbLocation);
q->showStatusMessage(tr("Starting Debugger: ") + loc + _c(' ') + gdbArgs.join(_(" ")));
m_gdbProc.start(loc, gdbArgs);
if (!m_gdbProc.waitForStarted()) {
m_gdbProc->start(loc, gdbArgs);
if (!m_gdbProc->waitForStarted()) {
QMessageBox::critical(q->mainWindow(), tr("Debugger Startup Failure"),
tr("Cannot start debugger: %1").arg(m_gdbProc.errorString()));
tr("Cannot start debugger: %1").arg(m_gdbProc->errorString()));
m_outputCollector.shutdown();
m_stubProc.blockSignals(true);
m_stubProc.stop();
......@@ -4198,7 +4200,7 @@ void GdbEngine::handleFetchDisassemblerByAddress0(const GdbResultRecord &record,
IDebuggerEngine *createGdbEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *opts)
{
opts->push_back(new GdbOptionsPage);
return new GdbEngine(parent);
return new GdbEngine(parent, new GdbProcess);
}
} // namespace Internal
......
......@@ -56,6 +56,7 @@ QT_END_NAMESPACE
namespace Debugger {
namespace Internal {
class DebuggerManager;
class IDebuggerManagerAccessForEngines;
class GdbResultRecord;
......@@ -72,13 +73,78 @@ enum DebuggingHelperState
DebuggingHelperUnavailable,
};
// GdbProcessBase is inherited by GdbProcess and the gdb/trk Adapter.
// In the GdbProcess case it's just a wrapper around a QProcess running
// gdb, in the Adapter case it's the interface to the gdb process in
// the whole rfomm/gdb/gdbserver combo.
class GdbProcessBase : public QObject
{
Q_OBJECT
public:
GdbProcessBase(QObject *parent) : QObject(parent) {}
virtual void start(const QString &program, const QStringList &args,
QIODevice::OpenMode mode = QIODevice::ReadWrite) = 0;
virtual void kill() = 0;
virtual void terminate() = 0;
virtual bool waitForStarted(int msecs = 30000) = 0;
virtual bool waitForFinished(int msecs = 30000) = 0;
virtual QProcess::ProcessState state() const = 0;
virtual QString errorString() const = 0;
virtual QByteArray readAllStandardError() = 0;
virtual QByteArray readAllStandardOutput() = 0;
virtual qint64 write(const char *data) = 0;
virtual void setWorkingDirectory(const QString &dir) = 0;
virtual void setEnvironment(const QStringList &env) = 0;
signals:
void error(QProcess::ProcessError);
void readyReadStandardOutput();
void readyReadStandardError();
void finished(int, QProcess::ExitStatus);
};
class GdbProcess : public GdbProcessBase
{
public:
GdbProcess(QObject *parent = 0)
: GdbProcessBase(parent)
{
connect(&m_proc, SIGNAL(error(QProcess::ProcessError)),
this, SIGNAL(error(QProcess::ProcessError)));
connect(&m_proc, SIGNAL(readyReadStandardOutput()),
this, SIGNAL(readyReadStandardOutput()));
connect(&m_proc, SIGNAL(readyReadStandardError()),
this, SIGNAL(readyReadStandardError()));
connect(&m_proc, SIGNAL(finished(int, QProcess::ExitStatus)),
this, SIGNAL(finished(int, QProcess::ExitStatus)));
}
void start(const QString &program, const QStringList &args,
QIODevice::OpenMode mode) { m_proc.start(program, args, mode); }
void kill() { m_proc.kill(); }
void terminate() { m_proc.terminate(); }
bool waitForStarted(int msecs) { return m_proc.waitForStarted(msecs); }
bool waitForFinished(int msecs) { return m_proc.waitForFinished(msecs); }
QProcess::ProcessState state() const { return m_proc.state(); }
QString errorString() const { return m_proc.errorString(); }
QByteArray readAllStandardError() { return m_proc.readAllStandardError(); }
QByteArray readAllStandardOutput() { return m_proc.readAllStandardOutput(); }
qint64 write(const char *data) { return m_proc.write(data); }
void setWorkingDirectory(const QString &dir) { m_proc.setWorkingDirectory(dir); }
void setEnvironment(const QStringList &env) { m_proc.setEnvironment(env); }
private:
QProcess m_proc;
};
class GdbEngine : public IDebuggerEngine
{
Q_OBJECT
public:
GdbEngine(DebuggerManager *parent);
GdbEngine(DebuggerManager *parent, GdbProcessBase *gdbProc);
~GdbEngine();
signals:
......@@ -251,7 +317,7 @@ private:
QByteArray m_inbuffer;
QProcess m_gdbProc;
GdbProcessBase *m_gdbProc;
QProcess m_uploadProc;
Core::Utils::ConsoleProcess m_stubProc;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment