File indexing completed on 2024-04-28 09:21:06

0001 /*
0002     SPDX-FileCopyrightText: 2009 George Kiagiadakis <gkiagia@users.sourceforge.net>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include <config-drkonqi.h>
0008 
0009 #include "crashedapplication.h"
0010 
0011 #if HAVE_STRSIGNAL && defined(Q_OS_UNIX)
0012 #include <clocale>
0013 #include <cstdlib>
0014 #include <cstring>
0015 #else
0016 #if defined(Q_OS_UNIX)
0017 #include <signal.h>
0018 #endif
0019 #endif
0020 
0021 #include <QDir>
0022 
0023 #include <KIO/CommandLauncherJob>
0024 
0025 #include "drkonqi_debug.h"
0026 
0027 CrashedApplication::CrashedApplication(int pid,
0028                                        int thread,
0029                                        int signalNumber,
0030                                        const QFileInfo &executable,
0031                                        const QString &version,
0032                                        const BugReportAddress &reportAddress,
0033                                        const QString &name,
0034                                        const QString &productName,
0035                                        const QDateTime &datetime,
0036                                        bool restarted,
0037                                        bool hasDeletedFiles,
0038                                        const QString &fakeBaseName,
0039                                        QObject *parent)
0040 
0041     : QObject(parent)
0042     , m_pid(pid)
0043     , m_signalNumber(signalNumber)
0044     , m_name(name)
0045     , m_executable(executable)
0046     , m_fakeBaseName(fakeBaseName)
0047     , m_version(version)
0048     , m_reportAddress(reportAddress)
0049     , m_productName(productName)
0050     , m_restarted(restarted)
0051     , m_thread(thread)
0052     , m_datetime(datetime)
0053     , m_hasDeletedFiles(hasDeletedFiles)
0054 
0055 {
0056 }
0057 
0058 CrashedApplication::~CrashedApplication()
0059 {
0060     if (!m_coreFile.isEmpty()) {
0061         const auto path = QFileInfo(m_coreFile).path();
0062         if (!path.isEmpty() && QFile::exists(path)) {
0063             qCDebug(DRKONQI_LOG) << "Cleaning up" << path;
0064             QDir(path).removeRecursively();
0065         }
0066     }
0067 };
0068 
0069 QString CrashedApplication::name() const
0070 {
0071     return m_name.isEmpty() ? fakeExecutableBaseName() : m_name;
0072 }
0073 
0074 QFileInfo CrashedApplication::executable() const
0075 {
0076     return m_executable;
0077 }
0078 
0079 QString CrashedApplication::fakeExecutableBaseName() const
0080 {
0081     if (!m_fakeBaseName.isEmpty()) {
0082         return m_fakeBaseName;
0083     } else {
0084         return m_executable.baseName();
0085     }
0086 }
0087 
0088 QString CrashedApplication::version() const
0089 {
0090     return m_version;
0091 }
0092 
0093 BugReportAddress CrashedApplication::bugReportAddress() const
0094 {
0095     return m_reportAddress;
0096 }
0097 
0098 QString CrashedApplication::productName() const
0099 {
0100     return m_productName;
0101 }
0102 
0103 int CrashedApplication::pid() const
0104 {
0105     return m_pid;
0106 }
0107 
0108 int CrashedApplication::signalNumber() const
0109 {
0110     return m_signalNumber;
0111 }
0112 
0113 QString CrashedApplication::signalName() const
0114 {
0115 #if HAVE_STRSIGNAL && defined(Q_OS_UNIX)
0116     const QByteArray originalLocale(std::setlocale(LC_MESSAGES, nullptr));
0117     std::setlocale(LC_MESSAGES, "C");
0118     const char *name = strsignal(m_signalNumber);
0119     std::setlocale(LC_MESSAGES, originalLocale.data() /* empty string if we got a nullptr */);
0120     return QString::fromLocal8Bit(name ? name : "Unknown");
0121 #else
0122     switch (m_signalNumber) {
0123 #if defined(Q_OS_UNIX)
0124     case SIGILL:
0125         return QLatin1String("SIGILL");
0126     case SIGABRT:
0127         return QLatin1String("SIGABRT");
0128     case SIGFPE:
0129         return QLatin1String("SIGFPE");
0130     case SIGSEGV:
0131         return QLatin1String("SIGSEGV");
0132     case SIGBUS:
0133         return QLatin1String("SIGBUS");
0134 #else
0135     case EXCEPTION_ACCESS_VIOLATION:
0136         return QLatin1String("EXCEPTION_ACCESS_VIOLATION");
0137     case EXCEPTION_DATATYPE_MISALIGNMENT:
0138         return QLatin1String("EXCEPTION_DATATYPE_MISALIGNMENT");
0139     case EXCEPTION_BREAKPOINT:
0140         return QLatin1String("EXCEPTION_BREAKPOINT");
0141     case EXCEPTION_SINGLE_STEP:
0142         return QLatin1String("EXCEPTION_SINGLE_STEP");
0143     case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
0144         return QLatin1String("EXCEPTION_ARRAY_BOUNDS_EXCEEDED");
0145     case EXCEPTION_FLT_DENORMAL_OPERAND:
0146         return QLatin1String("EXCEPTION_FLT_DENORMAL_OPERAND");
0147     case EXCEPTION_FLT_DIVIDE_BY_ZERO:
0148         return QLatin1String("EXCEPTION_FLT_DIVIDE_BY_ZERO");
0149     case EXCEPTION_FLT_INEXACT_RESULT:
0150         return QLatin1String("EXCEPTION_FLT_INEXACT_RESULT");
0151     case EXCEPTION_FLT_INVALID_OPERATION:
0152         return QLatin1String("EXCEPTION_FLT_INVALID_OPERATION");
0153     case EXCEPTION_FLT_OVERFLOW:
0154         return QLatin1String("EXCEPTION_FLT_OVERFLOW");
0155     case EXCEPTION_FLT_STACK_CHECK:
0156         return QLatin1String("EXCEPTION_FLT_STACK_CHECK");
0157     case EXCEPTION_FLT_UNDERFLOW:
0158         return QLatin1String("EXCEPTION_FLT_UNDERFLOW");
0159     case EXCEPTION_INT_DIVIDE_BY_ZERO:
0160         return QLatin1String("EXCEPTION_INT_DIVIDE_BY_ZERO");
0161     case EXCEPTION_INT_OVERFLOW:
0162         return QLatin1String("EXCEPTION_INT_OVERFLOW");
0163     case EXCEPTION_PRIV_INSTRUCTION:
0164         return QLatin1String("EXCEPTION_PRIV_INSTRUCTION");
0165     case EXCEPTION_IN_PAGE_ERROR:
0166         return QLatin1String("EXCEPTION_IN_PAGE_ERROR");
0167     case EXCEPTION_ILLEGAL_INSTRUCTION:
0168         return QLatin1String("EXCEPTION_ILLEGAL_INSTRUCTION");
0169     case EXCEPTION_NONCONTINUABLE_EXCEPTION:
0170         return QLatin1String("EXCEPTION_NONCONTINUABLE_EXCEPTION");
0171     case EXCEPTION_STACK_OVERFLOW:
0172         return QLatin1String("EXCEPTION_STACK_OVERFLOW");
0173     case EXCEPTION_INVALID_DISPOSITION:
0174         return QLatin1String("EXCEPTION_INVALID_DISPOSITION");
0175 #endif
0176     default:
0177         return QLatin1String("Unknown");
0178     }
0179 #endif
0180 }
0181 
0182 bool CrashedApplication::hasBeenRestarted() const
0183 {
0184     return m_restarted;
0185 }
0186 
0187 int CrashedApplication::thread() const
0188 {
0189     return m_thread;
0190 }
0191 
0192 const QDateTime &CrashedApplication::datetime() const
0193 {
0194     return m_datetime;
0195 }
0196 
0197 bool CrashedApplication::hasDeletedFiles() const
0198 {
0199     return m_hasDeletedFiles;
0200 }
0201 
0202 void CrashedApplication::restart()
0203 {
0204     if (m_restarted) {
0205         return;
0206     }
0207 
0208     // start the application via CommandLauncherJob so it runs in a new cgroup if possible.
0209     // if m_fakeBaseName is set, this means m_executable is the path to kdeinit4
0210     // so we need to use the fakeBaseName to restart the app
0211     auto job = new KIO::CommandLauncherJob(!m_fakeBaseName.isEmpty() ? m_fakeBaseName : m_executable.absoluteFilePath());
0212     if (const QString &id = DrKonqi::startupId(); !id.isEmpty()) {
0213         job->setStartupId(id.toUtf8());
0214     }
0215     connect(job, &KIO::CommandLauncherJob::result, this, [job, this] {
0216         m_restarted = (job->error() == KJob::NoError);
0217         if (!m_restarted) {
0218             qCWarning(DRKONQI_LOG) << "Failed to restart:" << job->error() << job->errorString();
0219         }
0220         Q_EMIT restarted(m_restarted);
0221     });
0222     job->start();
0223 }
0224 
0225 QString getSuggestedKCrashFilename(const CrashedApplication *app)
0226 {
0227     QString filename =
0228         app->fakeExecutableBaseName() + QLatin1Char('-') + app->datetime().toString(QStringLiteral("yyyyMMdd-hhmmss")) + QStringLiteral(".kcrash");
0229 
0230     if (filename.contains(QLatin1Char('/'))) {
0231         filename = filename.mid(filename.lastIndexOf(QLatin1Char('/')) + 1);
0232     }
0233 
0234     return filename;
0235 }
0236 
0237 #include "moc_crashedapplication.cpp"