diff --git a/src/drkonqi.h b/src/drkonqi.h --- a/src/drkonqi.h +++ b/src/drkonqi.h @@ -36,7 +36,7 @@ static CrashedApplication *crashedApplication(); static void saveReport(const QString & reportText, QWidget *parent = nullptr); - + static void shutdownSaveReport(); static void setSignal(int signal); static void setAppName(const QString &appName); static void setAppPath(const QString &appPath); diff --git a/src/drkonqi.cpp b/src/drkonqi.cpp --- a/src/drkonqi.cpp +++ b/src/drkonqi.cpp @@ -53,10 +53,13 @@ #include #include #include +#include #include "systeminformation.h" #include "crashedapplication.h" #include "drkonqibackends.h" +#include "debuggermanager.h" +#include "backtracegenerator.h" DrKonqi::DrKonqi() : m_signal(0) @@ -204,6 +207,54 @@ } } +// Helper functions for the shutdownSaveReport +namespace { + QString shutdownSaveString; + void saveReportAndQuit() + { + const QString dirname = QStandardPaths::writableLocation(QStandardPaths::CacheLocation); + // Try to create the directory to save the logs, if we can't open the directory, + // just bail out. no need to hold the shutdown process. + { + QDir dir; + if(!dir.mkpath(dirname)) { + qApp->quit(); + } + } + + const QString defname = dirname + + QLatin1Char('/') + + getSuggestedKCrashFilename(DrKonqi::crashedApplication()); + KMessageBox::sorry(nullptr, defname); + + QFile shutdownSaveFile(defname); + if (shutdownSaveFile.open(QIODevice::WriteOnly | QIODevice::Text)) { + QTextStream ts(&shutdownSaveFile); + ts << shutdownSaveString; + ts.flush(); + shutdownSaveFile.close(); + } + qApp->quit(); + } + + void appendNewLine(const QString& newLine) + { + shutdownSaveString += newLine; + } +} + +void DrKonqi::shutdownSaveReport() +{ + auto btGenerator = instance()->debuggerManager()->backtraceGenerator(); + shutdownSaveString.clear(); + + QObject::connect(btGenerator, &BacktraceGenerator::done, &saveReportAndQuit); + QObject::connect(btGenerator, &BacktraceGenerator::someError, &saveReportAndQuit); + QObject::connect(btGenerator, &BacktraceGenerator::failedToStart, &saveReportAndQuit); + QObject::connect(btGenerator, &BacktraceGenerator::newLine, &appendNewLine); + btGenerator->start(); +} + void DrKonqi::setSignal(int signal) { instance()->m_signal = signal; diff --git a/src/main.cpp b/src/main.cpp --- a/src/main.cpp +++ b/src/main.cpp @@ -34,6 +34,12 @@ #include #include #include +#include +#include + +#include +#include +#include #include #if HAVE_X11 @@ -47,6 +53,8 @@ #include "drkonqi.h" #include "drkonqidialog.h" #include "statusnotifier.h" +#include "debuggermanager.h" +#include "backtracegenerator.h" static const char version[] = PROJECT_VERSION; static const char description[] = I18N_NOOP("The KDE Crash Handler gives the user feedback " @@ -70,6 +78,18 @@ QObject::connect(statusNotifier, &StatusNotifier::expired, qApp, &QApplication::quit); QObject::connect(statusNotifier, &StatusNotifier::activated, &openDrKonqiDialog); } + + bool isShuttingDown() { + if (QDBusConnection::sessionBus().isConnected()) { + QDBusInterface remoteApp( QStringLiteral("org.kde.ksmserver"), + QStringLiteral("/KSMServer"), + QStringLiteral("org.kde.KSMServerInterface" )); + + QDBusReply reply = remoteApp.call( QStringLiteral("isShuttingDown") ); + return reply.isValid() ? reply.value() : false; + } + return false; + } } int main(int argc, char* argv[]) @@ -195,8 +215,10 @@ // if no notification service is running (eg. shell crashed, or other desktop environment) // and we didn't auto-restart the app, open DrKonqi dialog instead of showing an SNI - // and emitting a desktop notification - if (forceDialog || (!restarted && !StatusNotifier::notificationServiceRegistered())) { + // and emitting a desktop notification. + if (isShuttingDown()) { + DrKonqi::shutdownSaveReport(); + } else if (forceDialog || (!restarted && !StatusNotifier::notificationServiceRegistered())) { openDrKonqiDialog(); } else { requestDrKonqiDialog(restarted);