Commit 1ba9cf5d authored by Harald Sitter's avatar Harald Sitter 🏳️‍🌈
Browse files

prepare the backend before tracing

debuggermanager now plays negotiator between backend and generator so
that the backend can prepare itself for tracing.
specifically this will allow us to interface with coredumpd where we
might need to extract the dump for tracing just before starting the
trace. this will be possible with the new preparation dance between
generator, manager and backend.

instead of outright starting the generator now enters loading state and
emits `preparing()` to get the backend to prepare. once the backend is
prepared it in turn emits a signal to trigger further startup in the
generator.
parent e7c3069c
......@@ -53,9 +53,6 @@ void BacktraceGenerator::start()
Q_ASSERT(!m_temp);
m_parsedBacktrace.clear();
m_state = Loading;
emit starting();
if (!m_debugger.isValid() || !m_debugger.isInstalled()) {
qCWarning(DRKONQI_LOG) << "Debugger valid" << m_debugger.isValid() << "installed" << m_debugger.isInstalled();
......@@ -64,40 +61,9 @@ void BacktraceGenerator::start()
return;
}
m_proc = new KProcess;
m_proc->setEnv(QStringLiteral("LC_ALL"), QStringLiteral("C")); // force C locale
m_temp = new QTemporaryFile;
m_temp->open();
m_temp->write(m_debugger.backtraceBatchCommands().toLatin1());
m_temp->write("\n", 1);
m_temp->flush();
auto preamble = new QTemporaryFile(m_proc);
preamble->open();
preamble->write(m_debugger.preambleCommands().toUtf8());
preamble->write("\n", 1);
preamble->flush();
// start the debugger
QString str = m_debugger.command();
Debugger::expandString(str, Debugger::ExpansionUsageShell, m_temp->fileName(), preamble->fileName());
*m_proc << KShell::splitArgs(str);
m_proc->setOutputChannelMode(KProcess::OnlyStdoutChannel);
m_proc->setNextOpenMode(QIODevice::ReadWrite | QIODevice::Text);
// check if the debugger should take its input from a file we'll generate,
// and take the appropriate steps if so
QString stdinFile = m_debugger.backendValueOfParameter(QStringLiteral("ExecInputFile"));
Debugger::expandString(stdinFile, Debugger::ExpansionUsageShell, m_temp->fileName(), preamble->fileName());
if (!stdinFile.isEmpty() && QFile::exists(stdinFile)) {
m_proc->setStandardInputFile(stdinFile);
}
connect(m_proc, &KProcess::readyReadStandardOutput, this, &BacktraceGenerator::slotReadInput);
connect(m_proc, static_cast<void (KProcess::*)(int, QProcess::ExitStatus)>(&KProcess::finished), this, &BacktraceGenerator::slotProcessExited);
connect(m_proc, &KProcess::errorOccurred, this, &BacktraceGenerator::slotOnErrorOccurred);
m_proc->start();
m_state = Loading;
Q_EMIT preparing();
// DebuggerManager calls setBackendPrepared when it is ready for us to actually start.
}
void BacktraceGenerator::slotReadInput()
......@@ -190,3 +156,49 @@ void BacktraceGenerator::slotOnErrorOccurred(QProcess::ProcessError error)
break;
}
}
void BacktraceGenerator::setBackendPrepared()
{
// they should always be null before entering this function.
Q_ASSERT(!m_proc);
Q_ASSERT(!m_temp);
Q_ASSERT(m_state == Loading);
Q_EMIT starting();
m_proc = new KProcess;
m_proc->setEnv(QStringLiteral("LC_ALL"), QStringLiteral("C")); // force C locale
m_temp = new QTemporaryFile;
m_temp->open();
m_temp->write(m_debugger.backtraceBatchCommands().toLatin1());
m_temp->write("\n", 1);
m_temp->flush();
auto preamble = new QTemporaryFile(m_proc);
preamble->open();
preamble->write(m_debugger.preambleCommands().toUtf8());
preamble->write("\n", 1);
preamble->flush();
// start the debugger
QString str = m_debugger.command();
Debugger::expandString(str, Debugger::ExpansionUsageShell, m_temp->fileName(), preamble->fileName());
*m_proc << KShell::splitArgs(str);
m_proc->setOutputChannelMode(KProcess::OnlyStdoutChannel);
m_proc->setNextOpenMode(QIODevice::ReadWrite | QIODevice::Text);
// check if the debugger should take its input from a file we'll generate,
// and take the appropriate steps if so
QString stdinFile = m_debugger.backendValueOfParameter(QStringLiteral("ExecInputFile"));
Debugger::expandString(stdinFile, Debugger::ExpansionUsageShell, m_temp->fileName(), preamble->fileName());
if (!stdinFile.isEmpty() && QFile::exists(stdinFile)) {
m_proc->setStandardInputFile(stdinFile);
}
connect(m_proc, &KProcess::readyReadStandardOutput, this, &BacktraceGenerator::slotReadInput);
connect(m_proc, static_cast<void (KProcess::*)(int, QProcess::ExitStatus)>(&KProcess::finished), this, &BacktraceGenerator::slotProcessExited);
connect(m_proc, &KProcess::errorOccurred, this, &BacktraceGenerator::slotOnErrorOccurred);
m_proc->start();
}
......@@ -54,6 +54,9 @@ public:
return m_debugger;
}
// Called by manager when it is ready for us.
void setBackendPrepared();
public Q_SLOTS:
void start();
......@@ -63,6 +66,7 @@ Q_SIGNALS:
void someError();
void failedToStart();
void done();
void preparing();
private Q_SLOTS:
void slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus);
......
/*
SPDX-FileCopyrightText: 2009 George Kiagiadakis <gkiagia@users.sourceforge.net>
SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
......@@ -10,6 +11,7 @@
#include "backtracegenerator.h"
#include "debugger.h"
#include "debuggerlaunchers.h"
#include "drkonqibackends.h"
struct DebuggerManager::Private {
BacktraceGenerator *btGenerator = nullptr;
......@@ -18,8 +20,8 @@ struct DebuggerManager::Private {
DBusInterfaceAdaptor *dbusInterfaceAdaptor = nullptr;
};
DebuggerManager::DebuggerManager(const Debugger &internalDebugger, const QList<Debugger> &externalDebuggers, QObject *parent)
: QObject(parent)
DebuggerManager::DebuggerManager(const Debugger &internalDebugger, const QList<Debugger> &externalDebuggers, AbstractDrKonqiBackend *backendParent)
: QObject(backendParent)
, d(new Private)
{
d->btGenerator = new BacktraceGenerator(internalDebugger, this);
......@@ -27,6 +29,8 @@ DebuggerManager::DebuggerManager(const Debugger &internalDebugger, const QList<D
connect(d->btGenerator, &BacktraceGenerator::done, this, &DebuggerManager::onDebuggerFinished);
connect(d->btGenerator, &BacktraceGenerator::someError, this, &DebuggerManager::onDebuggerFinished);
connect(d->btGenerator, &BacktraceGenerator::failedToStart, this, &DebuggerManager::onDebuggerFinished);
connect(d->btGenerator, &BacktraceGenerator::preparing, backendParent, &AbstractDrKonqiBackend::prepareForDebugger);
connect(backendParent, &AbstractDrKonqiBackend::preparedForDebugger, d->btGenerator, &BacktraceGenerator::setBackendPrepared);
for (const Debugger &debugger : std::as_const(externalDebuggers)) {
if (debugger.isInstalled()) {
......
/*
SPDX-FileCopyrightText: 2009 George Kiagiadakis <gkiagia@users.sourceforge.net>
SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
......@@ -11,12 +12,13 @@
class BacktraceGenerator;
class Debugger;
class AbstractDebuggerLauncher;
class AbstractDrKonqiBackend;
class DebuggerManager : public QObject
{
Q_OBJECT
public:
explicit DebuggerManager(const Debugger &internalDebugger, const QList<Debugger> &externalDebuggers, QObject *parent = nullptr);
explicit DebuggerManager(const Debugger &internalDebugger, const QList<Debugger> &externalDebuggers, AbstractDrKonqiBackend *backendParent);
~DebuggerManager() override;
bool debuggerIsRunning() const;
......
......@@ -43,6 +43,10 @@ bool AbstractDrKonqiBackend::init()
return true;
}
void AbstractDrKonqiBackend::prepareForDebugger()
{
Q_EMIT preparedForDebugger();
}
KCrashBackend::~KCrashBackend()
{
......
......@@ -18,6 +18,7 @@ public:
using QObject::QObject;
virtual ~AbstractDrKonqiBackend();
virtual bool init();
virtual void prepareForDebugger();
inline CrashedApplication *crashedApplication() const
{
......@@ -29,6 +30,9 @@ public:
return m_debuggerManager;
}
Q_SIGNALS:
void preparedForDebugger();
protected:
virtual CrashedApplication *constructCrashedApplication() = 0;
virtual DebuggerManager *constructDebuggerManager() = 0;
......
Supports Markdown
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