Integrate Crashpad crash handler into CApplication

Crash handler launches an external crash handler executable called
swift_crashpad_handler. It monitores the parent process and produces
a local dump in case of a crash.
For release builds, the dump is also uploaded to a crash report server.

refs #490
This commit is contained in:
Roland Winklmeier
2016-07-27 13:35:13 +02:00
parent 4c82009ac1
commit e47aec223e
7 changed files with 91 additions and 2 deletions

View File

@@ -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

View File

@@ -1,4 +1,7 @@
{
"crashreportServerUrl": {
"url": "http://crashreports.swift-project.org:8090/crash_upload"
},
"dbHttpPort": 5080,
"dbHttpsPort": 50443,
"dbRootDirectoryUrl": {

View File

@@ -32,7 +32,6 @@
#include "blackmisc/stringutils.h"
#include "blackmisc/threadutils.h"
#include "blackmisc/verify.h"
#include "qcompilerdetection.h"
#include <stdbool.h>
#include <stdio.h>
@@ -54,6 +53,12 @@
#include <QtGlobal>
#include <cstdlib>
#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<std::string, std::string> 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<CrashpadClient>();
m_crashpadClient->StartHandler(qstringToFilePath(handler), qstringToFilePath(database),
serverUrl.getFullUrl().toStdString(), annotations, {}, false);
m_crashpadClient->UseHandler();
#endif
}
} // ns

View File

@@ -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<CCoreFacade> m_coreFacade; //!< core facade if any
QScopedPointer<CSetupReader> m_setupReader; //!< setup reader
QScopedPointer<CWebDataServices> 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<crashpad::CrashpadClient> m_crashpadClient;
std::unique_ptr<crashpad::CrashReportDatabase> m_crashReportDatabase;
};
} // namespace

View File

@@ -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 {

View File

@@ -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),