File indexing completed on 2024-03-24 17:01:26

0001 /*
0002     SPDX-FileCopyrightText: 2009 George Kiagiadakis <gkiagia@users.sourceforge.net>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 #include "debuggerlaunchers.h"
0007 
0008 #include <QCoreApplication>
0009 #include <QDBusConnection>
0010 
0011 #include "drkonqi_debug.h"
0012 #include <KProcess>
0013 #include <KShell>
0014 
0015 #include "crashedapplication.h"
0016 #include "detachedprocessmonitor.h"
0017 #include "drkonqi.h"
0018 
0019 #include "ptracer.h"
0020 
0021 DefaultDebuggerLauncher::DefaultDebuggerLauncher(const Debugger &debugger, DebuggerManager *parent)
0022     : AbstractDebuggerLauncher(parent)
0023     , m_debugger(debugger)
0024 {
0025     m_monitor = new DetachedProcessMonitor(this);
0026     connect(m_monitor, &DetachedProcessMonitor::processFinished, this, &DefaultDebuggerLauncher::onProcessFinished);
0027 }
0028 
0029 QString DefaultDebuggerLauncher::name() const
0030 {
0031     return m_debugger.displayName();
0032 }
0033 
0034 void DefaultDebuggerLauncher::start()
0035 {
0036     if (static_cast<DebuggerManager *>(parent())->debuggerIsRunning()) {
0037         qCWarning(DRKONQI_LOG) << "Another debugger is already running";
0038         return;
0039     }
0040 
0041     QString str = m_debugger.command();
0042     Debugger::expandString(str, Debugger::ExpansionUsageShell);
0043 
0044     Q_EMIT starting();
0045     int pid = KProcess::startDetached(KShell::splitArgs(str));
0046     if (pid > 0) {
0047         setPtracer(pid, DrKonqi::pid());
0048         m_monitor->startMonitoring(pid);
0049     } else {
0050         qCWarning(DRKONQI_LOG) << "Could not start debugger:" << name();
0051         Q_EMIT finished();
0052     }
0053 }
0054 
0055 void DefaultDebuggerLauncher::onProcessFinished()
0056 {
0057     setPtracer(QCoreApplication::applicationPid(), DrKonqi::pid());
0058     Q_EMIT finished();
0059 }
0060 
0061 DBusInterfaceLauncher::DBusInterfaceLauncher(const QString &name, qint64 pid, DBusInterfaceAdaptor *parent)
0062     : AbstractDebuggerLauncher(parent)
0063     , m_name(name)
0064     , m_pid(pid)
0065 {
0066 }
0067 
0068 QString DBusInterfaceLauncher::name() const
0069 {
0070     return m_name;
0071 }
0072 
0073 void DBusInterfaceLauncher::start()
0074 {
0075     Q_EMIT starting();
0076 
0077     setPtracer(m_pid, DrKonqi::pid());
0078 
0079     Q_EMIT static_cast<DBusInterfaceAdaptor *>(parent())->acceptDebuggingApplication(m_name);
0080 }
0081 
0082 DBusInterfaceAdaptor::DBusInterfaceAdaptor(DebuggerManager *parent)
0083     : QDBusAbstractAdaptor(parent)
0084 {
0085     Q_ASSERT(parent);
0086 
0087     if (QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.drkonqi.PID%1").arg(pid()))) {
0088         QDBusConnection::sessionBus().registerObject(QStringLiteral("/debugger"), parent);
0089     }
0090 }
0091 
0092 int DBusInterfaceAdaptor::pid()
0093 {
0094     return DrKonqi::crashedApplication()->pid();
0095 }
0096 
0097 void DBusInterfaceAdaptor::registerDebuggingApplication(const QString &name, qint64 pid)
0098 {
0099     if (!name.isEmpty() && !m_launchers.contains(name)) {
0100         auto launcher = new DBusInterfaceLauncher(name, pid, this);
0101         m_launchers.insert(name, launcher);
0102         static_cast<DebuggerManager *>(parent())->addDebugger(launcher, true);
0103     }
0104 }
0105 
0106 void DBusInterfaceAdaptor::debuggingFinished(const QString &name)
0107 {
0108     auto it = m_launchers.find(name);
0109     if (it != m_launchers.end()) {
0110         setPtracer(QCoreApplication::applicationPid(), DrKonqi::pid());
0111         Q_EMIT it.value()->finished();
0112     }
0113 }
0114 
0115 void DBusInterfaceAdaptor::debuggerClosed(const QString &name)
0116 {
0117     auto it = m_launchers.find(name);
0118     if (it != m_launchers.end()) {
0119         Q_EMIT it.value()->invalidated();
0120         m_launchers.erase(it);
0121     }
0122 }