File indexing completed on 2024-12-08 10:52:35
0001 /* 0002 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0003 SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org> 0004 */ 0005 0006 #include "NotifierTruck.h" 0007 0008 #include <chrono> 0009 0010 #include <QCoreApplication> 0011 #include <QFile> 0012 #include <QProcess> 0013 #include <QTimer> 0014 0015 #include <KNotification> 0016 #include <KTerminalLauncherJob> 0017 0018 #include "../coredump.h" 0019 0020 using namespace std::chrono_literals; 0021 0022 bool NotifyTruck::handle(const Coredump &dump) 0023 { 0024 auto notification = new KNotification(QStringLiteral("applicationcrash")); 0025 0026 // immediate exit signal. This gets disconnected should `activated` arrive first (in that case we 0027 // want to wait for the terminal app to start and not exit on further notification signals) 0028 QObject::connect(notification, &KNotification::closed, this, [this, notification] { 0029 notification->disconnect(this); 0030 qApp->exit(0); 0031 }); 0032 0033 if (!QFile::exists(dump.filename)) { 0034 notification->setTitle(QStringLiteral("The warpcore has gone missing")); 0035 notification->setText(QStringLiteral("%1 [%2] crashed but has no core file").arg(dump.exe, QString::number(dump.pid))); 0036 } else { 0037 notification->setTitle(QStringLiteral("He's dead, Jim")); 0038 notification->setText(QStringLiteral("%1 [%2]").arg(dump.exe, QString::number(dump.pid))); 0039 notification->setActions({QStringLiteral("gdb")}); 0040 0041 const auto pid = dump.pid; 0042 0043 QObject::connect(notification, &KNotification::activated, notification, [pid, this, notification]() { 0044 notification->disconnect(this); 0045 auto job = new KTerminalLauncherJob(QStringLiteral("coredumpctl gdb %1").arg(QString::number(pid)), this); 0046 connect(job, &KJob::result, this, [job] { 0047 if (job->error() != KJob::NoError) { 0048 qWarning() << job->errorText(); 0049 } 0050 qApp->exit(0); 0051 }); 0052 job->start(); 0053 0054 // Just in case the launcher job bugs out also add a timer. 0055 auto startTimeout = new QTimer(this); 0056 startTimeout->setInterval(16s); 0057 connect(startTimeout, &QTimer::timeout, this, [] { 0058 qApp->exit(0); 0059 }); 0060 startTimeout->start(); 0061 }); 0062 } 0063 0064 notification->setFlags(KNotification::DefaultEvent | KNotification::SkipGrouping); 0065 notification->sendEvent(); 0066 0067 // KNotification internally depends on an eventloop to communicate over dbus. We therefore start the 0068 // eventloop here. ::handle() is expected to be blocking so this has no adverse effects. 0069 // The eventloop is either exited when the notification gets closed or when the debugger has started. 0070 qApp->exec(); 0071 return true; 0072 }