diff --git a/externals b/externals index 009fd2051..be1197e13 160000 --- a/externals +++ b/externals @@ -1 +1 @@ -Subproject commit 009fd20510821fb8e24aa9773ad8761b4b01040f +Subproject commit be1197e13264cc23416af92f7a6bcc85e42132f0 diff --git a/mkspecs/features/common_pre.prf b/mkspecs/features/common_pre.prf index feb2924ed..471763772 100644 --- a/mkspecs/features/common_pre.prf +++ b/mkspecs/features/common_pre.prf @@ -123,6 +123,8 @@ isEmpty(EXTERNALSROOT) { INCLUDEPATH *= $$EXTERNALSROOT/common/include INCLUDEPATH *= $$EXTERNALSROOT/$$basename(QMAKESPEC)/include +INCLUDEPATH *= $$EXTERNALSROOT/common/include/crashpad +INCLUDEPATH *= $$EXTERNALSROOT/common/include/mini_chromium equals(WORD_SIZE,64): EXTERNALSDIR = $$EXTERNALSROOT/$$basename(QMAKESPEC)/lib64 equals(WORD_SIZE,32): EXTERNALSDIR = $$EXTERNALSROOT/$$basename(QMAKESPEC)/lib32 diff --git a/resources/share/shared/bootstrap/bootstrap.json b/resources/share/shared/bootstrap/bootstrap.json index 30d6b6674..f8ce9a2bc 100644 --- a/resources/share/shared/bootstrap/bootstrap.json +++ b/resources/share/shared/bootstrap/bootstrap.json @@ -1,4 +1,7 @@ { + "crashreportServerUrl": { + "url": "http://crashreports.swift-project.org:8090/crash_upload" + }, "dbHttpPort": 5080, "dbHttpsPort": 50443, "dbRootDirectoryUrl": { diff --git a/src/blackcore/application.cpp b/src/blackcore/application.cpp index 20329a9c3..5d401bb29 100644 --- a/src/blackcore/application.cpp +++ b/src/blackcore/application.cpp @@ -32,7 +32,6 @@ #include "blackmisc/stringutils.h" #include "blackmisc/threadutils.h" #include "blackmisc/verify.h" -#include "qcompilerdetection.h" #include #include @@ -54,6 +53,12 @@ #include #include +#ifdef BLACK_USE_CRASHPAD +#include "crashpad/client/crashpad_client.h" +#include "crashpad/client/crash_report_database.h" +#include "crashpad/client/settings.h" +#endif + using namespace BlackConfig; using namespace BlackMisc; using namespace BlackMisc::Network; @@ -65,6 +70,7 @@ using namespace BlackCore::Context; using namespace BlackCore::Vatsim; using namespace BlackCore::Data; using namespace BlackCore::Db; +using namespace crashpad; BlackCore::CApplication *sApp = nullptr; // set by constructor @@ -222,6 +228,9 @@ namespace BlackCore // Settings are distributed via DBus. So only one application is responsible for saving. `enableLocalSave()` means // "this is the application responsible for saving". If swiftgui requests a setting to be saved, it is sent to swiftcore and saved by swiftcore. CSettingsCache::instance()->enableLocalSave(); + + // From this moment on, we have settings, so enable crash handler. + initCrashHandler(); } if (waitForStart) @@ -964,4 +973,54 @@ namespace BlackCore } return CUrlList(); } + + #ifdef BLACK_USE_CRASHPAD + base::FilePath qstringToFilePath(const QString &str) + { + #ifdef Q_OS_WIN + return base::FilePath(str.toStdWString()); + #else + return base::FilePath(str.toStdString()); + #endif + } + #endif + + void CApplication::initCrashHandler() + { + #ifdef BLACK_USE_CRASHPAD + // No crash handling for unit tests + if (isUnitTest()) { return; } + + static const QString extension = CBuildConfig::isRunningOnWindowsNtPlatform() ? ".exe" : QString(); + static const QString handler = CDirectoryUtils::applicationDirectoryPath() + "/" + "swift_crashpad_handler" + extension; + static const QString database = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + + "/org.swift-project/" + + CDirectoryUtils::normalizedApplicationDirectory() + + "/crashpad"; + + if (!QFileInfo::exists(handler)) + { + CLogMessage(this).warning("%1 not found. Cannot init crash handler!") << handler; + return; + } + + CUrl serverUrl; + if (CBuildConfig::isReleaseBuild()) { serverUrl = getGlobalSetup().getCrashreportServerUrl(); } + + std::map annotations; + + // Caliper (mini-breakpad-server) annotations + annotations["prod"] = executable().toStdString(); + annotations["ver"] = CVersion::version().toStdString(); + + m_crashReportDatabase = CrashReportDatabase::Initialize(qstringToFilePath(database)); + auto settings = m_crashReportDatabase->GetSettings(); + settings->SetUploadsEnabled(true); + m_crashpadClient = std::make_unique(); + m_crashpadClient->StartHandler(qstringToFilePath(handler), qstringToFilePath(database), + serverUrl.getFullUrl().toStdString(), annotations, {}, false); + m_crashpadClient->UseHandler(); + #endif + } + } // ns diff --git a/src/blackcore/application.h b/src/blackcore/application.h index a50f92187..556140486 100644 --- a/src/blackcore/application.h +++ b/src/blackcore/application.h @@ -37,6 +37,10 @@ #include "blackmisc/statusmessage.h" #include "blackmisc/statusmessagelist.h" +#if defined(Q_CC_MSVC) || defined(Q_OS_OSX) // Crashpad only supported on MSVC and MacOS/X +#define BLACK_USE_CRASHPAD +#endif + class QHttpMultiPart; class QNetworkReply; class QNetworkRequest; @@ -47,6 +51,12 @@ namespace BlackMisc class CLogCategoryList; } +namespace crashpad +{ + class CrashpadClient; + class CrashReportDatabase; +} + namespace BlackCore { class CCoreFacade; @@ -402,6 +412,8 @@ namespace BlackCore //! Async. start when setup is loaded bool asyncWebAndContextStart(); + void initCrashHandler(); + QScopedPointer m_coreFacade; //!< core facade if any QScopedPointer m_setupReader; //!< setup reader QScopedPointer m_webDataServices; //!< web data services @@ -422,6 +434,8 @@ namespace BlackCore bool m_unitTest = false; //!< is UNIT test bool m_autoSaveSettings = true;//!< automatically saving all settings + std::unique_ptr m_crashpadClient; + std::unique_ptr m_crashReportDatabase; }; } // namespace diff --git a/src/blackcore/blackcore.pro b/src/blackcore/blackcore.pro index 23d9d0d35..0a9ddd6a9 100644 --- a/src/blackcore/blackcore.pro +++ b/src/blackcore/blackcore.pro @@ -41,6 +41,12 @@ LIBS *= -lvatlib DESTDIR = $$DestRoot/lib DLLDESTDIR = $$DestRoot/bin +win32-msvc* { + CONFIG(debug, debug|release): LIBS *= -lcrashpad_clientd -lcrashpad_utild -lbased -lRpcrt4 + CONFIG(release, debug|release): LIBS *= -lcrashpad_client -lcrashpad_util -lbase -lRpcrt4 +} +macx: LIBS *= -lcrashpad_client -lcrashpad_util -lbase -lbsm -framework Security + OTHER_FILES += readme.txt *.xml win32 { diff --git a/src/blackcore/data/globalsetup.h b/src/blackcore/data/globalsetup.h index f4041770b..902d3ffef 100644 --- a/src/blackcore/data/globalsetup.h +++ b/src/blackcore/data/globalsetup.h @@ -82,6 +82,9 @@ namespace BlackCore //! Same type? bool hasSameType(const CGlobalSetup &otherSetup) const; + //! Crash report server url + BlackMisc::Network::CUrl getCrashreportServerUrl() const { return m_crashreportServerUrl; } + //! Home page url BlackMisc::Network::CUrl getDbHomePageUrl() const; @@ -171,6 +174,7 @@ namespace BlackCore int m_dbHttpPort = 80; //!< port int m_dbHttpsPort = 443; //!< SSL port bool m_development = false; //!< dev. version? + BlackMisc::Network::CUrl m_crashreportServerUrl; //!< crash report server BlackMisc::Network::CUrl m_dbRootDirectoryUrl; //!< Root directory of DB BlackMisc::Network::CUrl m_vatsimBookingsUrl; //!< ATC bookings BlackMisc::Network::CUrlList m_vatsimMetarsUrls; //!< METAR data @@ -187,6 +191,7 @@ namespace BlackCore CGlobalSetup, BLACK_METAMEMBER(wasLoaded), BLACK_METAMEMBER(timestampMSecsSinceEpoch), + BLACK_METAMEMBER(crashreportServerUrl), BLACK_METAMEMBER(dbRootDirectoryUrl), BLACK_METAMEMBER(dbHttpPort), BLACK_METAMEMBER(dbHttpsPort),