// Copyright (C) 2017 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "qtsystemexceptionhandler.h" #include #include #include #include #include #include #if defined(Q_OS_LINUX) # include "client/linux/handler/exception_handler.h" #elif defined(Q_OS_WIN) # include "client/windows/handler/exception_handler.h" #elif defined(Q_OS_MACOS) # include "client/mac/handler/exception_handler.h" #endif #if defined(Q_OS_LINUX) static bool exceptionHandlerCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* /*context*/, bool succeeded) { if (!succeeded) return succeeded; const QStringList argumentList = { QString::fromLocal8Bit(descriptor.path()), QString::number(QtSystemExceptionHandler::startTime().toTime_t()), QCoreApplication::applicationName(), QCoreApplication::applicationVersion(), QtSystemExceptionHandler::plugins(), QtSystemExceptionHandler::buildVersion(), QCoreApplication::applicationFilePath() }; return !QProcess::execute(QtSystemExceptionHandler::crashHandlerPath(), argumentList); } #elif defined(Q_OS_MACOS) static bool exceptionHandlerCallback(const char *dump_dir, const char *minidump_id, void *context, bool succeeded) { Q_UNUSED(context); if (!succeeded) return succeeded; const QString path = QString::fromLocal8Bit(dump_dir) + '/' + QString::fromLocal8Bit(minidump_id) + ".dmp"; const QStringList argumentList = { path, QString::number(QtSystemExceptionHandler::startTime().toTime_t()), QCoreApplication::applicationName(), QCoreApplication::applicationVersion(), QtSystemExceptionHandler::plugins(), QtSystemExceptionHandler::buildVersion(), QCoreApplication::applicationFilePath() }; return !QProcess::execute(QtSystemExceptionHandler::crashHandlerPath(), argumentList); } #elif defined(Q_OS_WIN) static bool exceptionHandlerCallback(const wchar_t* dump_path, const wchar_t* minidump_id, void* context, EXCEPTION_POINTERS* exinfo, MDRawAssertionInfo* assertion, bool succeeded) { Q_UNUSED(assertion); Q_UNUSED(exinfo); Q_UNUSED(context); if (!succeeded) return succeeded; const QString path = QString::fromWCharArray(dump_path, int(wcslen(dump_path))) + '/' + QString::fromWCharArray(minidump_id, int(wcslen(minidump_id))) + ".dmp"; const QStringList argumentList = { path, QString::number(QtSystemExceptionHandler::startTime().toTime_t()), QCoreApplication::applicationName(), QCoreApplication::applicationVersion(), QtSystemExceptionHandler::plugins(), QtSystemExceptionHandler::buildVersion(), QCoreApplication::applicationFilePath() }; return !QProcess::execute(QtSystemExceptionHandler::crashHandlerPath(), argumentList); } #endif static QDateTime s_startTime; static QString s_plugins; static QString s_buildVersion; static QString s_crashHandlerPath; #if defined(Q_OS_LINUX) QtSystemExceptionHandler::QtSystemExceptionHandler(const QString &libexecPath) : exceptionHandler(new google_breakpad::ExceptionHandler( google_breakpad::MinidumpDescriptor(QDir::tempPath().toStdString()), NULL, exceptionHandlerCallback, NULL, true, -1)) { init(libexecPath); } #elif defined(Q_OS_MACOS) QtSystemExceptionHandler::QtSystemExceptionHandler(const QString &libexecPath) : exceptionHandler(new google_breakpad::ExceptionHandler( QDir::tempPath().toStdString(), NULL, exceptionHandlerCallback, NULL, true, NULL)) { init(libexecPath); } #elif defined(Q_OS_WIN) QtSystemExceptionHandler::QtSystemExceptionHandler(const QString &libexecPath) : exceptionHandler(new google_breakpad::ExceptionHandler( QDir::tempPath().toStdWString(), NULL, exceptionHandlerCallback, NULL, google_breakpad::ExceptionHandler::HANDLER_ALL)) { init(libexecPath); } #else QtSystemExceptionHandler::QtSystemExceptionHandler(const QString & /*libexecPath*/) : exceptionHandler(0) { } #endif void QtSystemExceptionHandler::init(const QString &libexecPath) { s_startTime = QDateTime::currentDateTime(); s_crashHandlerPath = libexecPath + Utils::HostOsInfo::withExecutableSuffix("/qtcrashhandler"); } QtSystemExceptionHandler::~QtSystemExceptionHandler() { #ifdef ENABLE_QT_BREAKPAD delete exceptionHandler; #endif } void QtSystemExceptionHandler::setPlugins(const QStringList &pluginNameList) { s_plugins = QString("{%1}").arg(pluginNameList.join(",")); } void QtSystemExceptionHandler::setBuildVersion(const QString &version) { s_buildVersion = version; } QString QtSystemExceptionHandler::buildVersion() { return s_buildVersion; } QString QtSystemExceptionHandler::plugins() { return s_plugins; } void QtSystemExceptionHandler::setCrashHandlerPath(const QString &crashHandlerPath) { s_crashHandlerPath = crashHandlerPath; } QString QtSystemExceptionHandler::crashHandlerPath() { return s_crashHandlerPath; } void QtSystemExceptionHandler::crash() { int *a = (int*)0x42; fprintf(stdout, "Going to crash...\n"); fprintf(stdout, "A = %d", *a); } QDateTime QtSystemExceptionHandler::startTime() { return s_startTime; }