mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
Rework crashpad initialization
* Don't abort on startup if we can't find our own path * Try to locate our own path by looking in /proc in Linux -- should fix AppImage issues * Add extensive logging
This commit is contained in:
parent
567b0d84ef
commit
186e784d89
2 changed files with 65 additions and 4 deletions
|
@ -13,7 +13,10 @@
|
|||
#define hifi_CrashHandler_h
|
||||
|
||||
#include <string>
|
||||
class QCoreApplication;
|
||||
#include <QCoreApplication>
|
||||
#include <QLoggingCategory>
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(crash_handler)
|
||||
|
||||
bool startCrashHandler(std::string appPath);
|
||||
void setCrashAnnotation(std::string name, std::string value);
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include "CrashHandler.h"
|
||||
|
||||
Q_LOGGING_CATEGORY(crash_handler, "vircadia.crash_handler")
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <vector>
|
||||
|
@ -141,6 +143,10 @@ static const QString CRASHPAD_HANDLER_NAME{ "crashpad_handler.exe" };
|
|||
static const QString CRASHPAD_HANDLER_NAME{ "crashpad_handler" };
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// The area within this #ifdef is specific to the Microsoft C++ compiler
|
||||
|
@ -311,8 +317,38 @@ void checkUnhandledExceptionHook() {
|
|||
// ------------------------------------------------------------------------------------------------
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
// Locate the full path to the binary's directory
|
||||
static QString findBinaryDir() {
|
||||
// Normally we'd just use QCoreApplication::applicationDirPath(), but we can't.
|
||||
// That function needs the QApplication to be created first, and Crashpad is initialized as early as possible,
|
||||
// which is well before QApplication, so that function throws out a warning and returns ".".
|
||||
//
|
||||
// So we must do things the hard way here. In particular this is needed to correctly handle things in AppImage
|
||||
// on Linux. On Windows and MacOS falling back to argv[0] should be fine.
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
// Find outselves by looking at /proc/<PID>/exe
|
||||
pid_t ourPid = getpid();
|
||||
QString exeLink = QString("/proc/%1/exe").arg(ourPid);
|
||||
qCDebug(crash_handler) << "Looking at" << exeLink;
|
||||
|
||||
QFileInfo exeLinkInfo(exeLink);
|
||||
if (exeLinkInfo.isSymLink()) {
|
||||
QFileInfo exeInfo( exeLinkInfo.symLinkTarget() );
|
||||
qCDebug(crash_handler) << "exe symlink points at" << exeInfo;
|
||||
return exeInfo.absoluteDir().absolutePath();
|
||||
} else {
|
||||
qCWarning(crash_handler) << exeLink << "isn't a symlink. /proc not mounted?";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool startCrashHandler(std::string appPath) {
|
||||
if (BACKTRACE_URL.empty() || BACKTRACE_TOKEN.empty()) {
|
||||
qCCritical(crash_handler) << "Backtrace URL or token not set, crash handler disabled.";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -338,11 +374,29 @@ bool startCrashHandler(std::string appPath) {
|
|||
const auto crashpadDbPath = crashpadDbDir.toStdString() + "/" + crashpadDbName;
|
||||
|
||||
// Locate Crashpad handler
|
||||
const QFileInfo interfaceBinary{ QString::fromStdString(appPath) };
|
||||
const QDir interfaceDir = interfaceBinary.dir();
|
||||
assert(interfaceDir.exists(CRASHPAD_HANDLER_NAME));
|
||||
QString binaryDir = findBinaryDir();
|
||||
QDir interfaceDir;
|
||||
|
||||
if ( !binaryDir.isEmpty() ) {
|
||||
// Locating ourselves by argv[0] fails in the case of AppImage on Linux, as we get the AppImage
|
||||
// itself in there. If we have a platform-specific method, and it succeeds, we use that instead
|
||||
// of argv.
|
||||
qCDebug(crash_handler) << "Locating own directory by platform-specific method";
|
||||
interfaceDir.setPath(binaryDir);
|
||||
} else {
|
||||
qCDebug(crash_handler) << "Locating own directory by argv[0]";
|
||||
interfaceDir.setPath(QString::fromStdString(appPath));
|
||||
}
|
||||
|
||||
if (!interfaceDir.exists(CRASHPAD_HANDLER_NAME)) {
|
||||
qCCritical(crash_handler) << "Failed to find" << CRASHPAD_HANDLER_NAME << "in" << interfaceDir << ", can't start crash handler";
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string CRASHPAD_HANDLER_PATH = interfaceDir.filePath(CRASHPAD_HANDLER_NAME).toStdString();
|
||||
|
||||
qCDebug(crash_handler) << "Crashpad handler found at" << QString::fromStdString(CRASHPAD_HANDLER_PATH);
|
||||
|
||||
// Setup different file paths
|
||||
base::FilePath::StringType dbPath;
|
||||
base::FilePath::StringType handlerPath;
|
||||
|
@ -352,8 +406,10 @@ bool startCrashHandler(std::string appPath) {
|
|||
base::FilePath db(dbPath);
|
||||
base::FilePath handler(handlerPath);
|
||||
|
||||
qCDebug(crash_handler) << "Opening crashpad database" << QString::fromStdString(crashpadDbPath);
|
||||
auto database = crashpad::CrashReportDatabase::Initialize(db);
|
||||
if (database == nullptr || database->GetSettings() == nullptr) {
|
||||
qCCritical(crash_handler) << "Failed to open crashpad database" << QString::fromStdString(crashpadDbPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -361,6 +417,7 @@ bool startCrashHandler(std::string appPath) {
|
|||
database->GetSettings()->SetUploadsEnabled(true);
|
||||
|
||||
if (!client->StartHandler(handler, db, db, BACKTRACE_URL, annotations, arguments, true, true)) {
|
||||
qCCritical(crash_handler) << "Failed to start crashpad handler";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -369,6 +426,7 @@ bool startCrashHandler(std::string appPath) {
|
|||
gl_crashpadUnhandledExceptionFilter = SetUnhandledExceptionFilter(unhandledExceptionHandler);
|
||||
#endif
|
||||
|
||||
qCInfo(crash_handler) << "Crashpad initialized";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue