mirror of
https://github.com/overte-org/overte.git
synced 2025-04-14 07:47:30 +02:00
Merge pull request #365 from daleglass/linux_crash_handler
Linux crash handler
This commit is contained in:
commit
45f2b672b5
6 changed files with 98 additions and 11 deletions
22
cmake/externals/crashpad/CMakeLists.txt
vendored
22
cmake/externals/crashpad/CMakeLists.txt
vendored
|
@ -35,6 +35,25 @@ elseif (APPLE)
|
||||||
|
|
||||||
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
||||||
|
|
||||||
|
set(BIN_RELEASE_PATH "${SOURCE_DIR}/out/Release")
|
||||||
|
set(BIN_EXT "")
|
||||||
|
set(LIB_RELEASE_PATH "${SOURCE_DIR}/out/Release/lib")
|
||||||
|
set(LIB_DEBUG_PATH "${SOURCE_DIR}/out/Debug/lib")
|
||||||
|
set(LIB_PREFIX "lib")
|
||||||
|
set(LIB_EXT "a")
|
||||||
|
elseif (UNIX)
|
||||||
|
ExternalProject_Add(
|
||||||
|
${EXTERNAL_NAME}
|
||||||
|
URL "${EXTERNAL_BUILD_ASSETS}/dependencies/crashpad_linux_f1943fcb.tar.bz2"
|
||||||
|
URL_MD5 e0949e5988905471c63c399833879482
|
||||||
|
CONFIGURE_COMMAND ""
|
||||||
|
BUILD_COMMAND ""
|
||||||
|
INSTALL_COMMAND ""
|
||||||
|
LOG_DOWNLOAD 1
|
||||||
|
)
|
||||||
|
|
||||||
|
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
||||||
|
|
||||||
set(BIN_RELEASE_PATH "${SOURCE_DIR}/out/Release")
|
set(BIN_RELEASE_PATH "${SOURCE_DIR}/out/Release")
|
||||||
set(BIN_EXT "")
|
set(BIN_EXT "")
|
||||||
set(LIB_RELEASE_PATH "${SOURCE_DIR}/out/Release/lib")
|
set(LIB_RELEASE_PATH "${SOURCE_DIR}/out/Release/lib")
|
||||||
|
@ -43,8 +62,7 @@ elseif (APPLE)
|
||||||
set(LIB_EXT "a")
|
set(LIB_EXT "a")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (WIN32 OR APPLE)
|
if (WIN32 OR APPLE OR UNIX)
|
||||||
|
|
||||||
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE PATH "List of Crashpad include directories")
|
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE PATH "List of Crashpad include directories")
|
||||||
|
|
||||||
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${LIB_RELEASE_PATH}/${LIB_PREFIX}crashpad_client.${LIB_EXT} CACHE FILEPATH "Path to Crashpad release library")
|
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${LIB_RELEASE_PATH}/${LIB_PREFIX}crashpad_client.${LIB_EXT} CACHE FILEPATH "Path to Crashpad release library")
|
||||||
|
|
|
@ -11,24 +11,29 @@
|
||||||
|
|
||||||
macro(add_crashpad)
|
macro(add_crashpad)
|
||||||
set (USE_CRASHPAD TRUE)
|
set (USE_CRASHPAD TRUE)
|
||||||
|
message(STATUS "Checking crashpad config")
|
||||||
|
|
||||||
if ("$ENV{CMAKE_BACKTRACE_URL}" STREQUAL "")
|
if ("$ENV{CMAKE_BACKTRACE_URL}" STREQUAL "")
|
||||||
|
message(STATUS "Checking crashpad config - CMAKE_BACKTRACE_URL is not set, disabled.")
|
||||||
set(USE_CRASHPAD FALSE)
|
set(USE_CRASHPAD FALSE)
|
||||||
else()
|
else()
|
||||||
set(CMAKE_BACKTRACE_URL $ENV{CMAKE_BACKTRACE_URL})
|
set(CMAKE_BACKTRACE_URL $ENV{CMAKE_BACKTRACE_URL})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if ("$ENV{CMAKE_BACKTRACE_TOKEN}" STREQUAL "")
|
if ("$ENV{CMAKE_BACKTRACE_TOKEN}" STREQUAL "")
|
||||||
|
message(STATUS "Checking crashpad config - CMAKE_BACKTRACE_TOKEN is not set, disabled.")
|
||||||
set(USE_CRASHPAD FALSE)
|
set(USE_CRASHPAD FALSE)
|
||||||
else()
|
else()
|
||||||
set(CMAKE_BACKTRACE_TOKEN $ENV{CMAKE_BACKTRACE_TOKEN})
|
set(CMAKE_BACKTRACE_TOKEN $ENV{CMAKE_BACKTRACE_TOKEN})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if ((WIN32 OR APPLE) AND USE_CRASHPAD)
|
if (USE_CRASHPAD)
|
||||||
|
message(STATUS "Checking crashpad config - enabled.")
|
||||||
get_property(CRASHPAD_CHECKED GLOBAL PROPERTY CHECKED_FOR_CRASHPAD_ONCE)
|
get_property(CRASHPAD_CHECKED GLOBAL PROPERTY CHECKED_FOR_CRASHPAD_ONCE)
|
||||||
if (NOT CRASHPAD_CHECKED)
|
if (NOT CRASHPAD_CHECKED)
|
||||||
|
|
||||||
add_dependency_external_projects(crashpad)
|
add_dependency_external_projects(crashpad)
|
||||||
find_package(crashpad REQUIRED)
|
find_package(Crashpad REQUIRED)
|
||||||
|
|
||||||
set_property(GLOBAL PROPERTY CHECKED_FOR_CRASHPAD_ONCE TRUE)
|
set_property(GLOBAL PROPERTY CHECKED_FOR_CRASHPAD_ONCE TRUE)
|
||||||
endif()
|
endif()
|
||||||
|
@ -38,7 +43,7 @@ macro(add_crashpad)
|
||||||
add_definitions(-DCMAKE_BACKTRACE_TOKEN=\"${CMAKE_BACKTRACE_TOKEN}\")
|
add_definitions(-DCMAKE_BACKTRACE_TOKEN=\"${CMAKE_BACKTRACE_TOKEN}\")
|
||||||
|
|
||||||
target_include_directories(${TARGET_NAME} PRIVATE ${CRASHPAD_INCLUDE_DIRS})
|
target_include_directories(${TARGET_NAME} PRIVATE ${CRASHPAD_INCLUDE_DIRS})
|
||||||
target_link_libraries(${TARGET_NAME} ${CRASHPAD_LIBRARY} ${CRASHPAD_BASE_LIBRARY} ${CRASHPAD_UTIL_LIBRARY})
|
target_link_libraries(${TARGET_NAME} ${CRASHPAD_LIBRARY} ${CRASHPAD_UTIL_LIBRARY} ${CRASHPAD_BASE_LIBRARY})
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS "/ignore:4099")
|
set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS "/ignore:4099")
|
||||||
|
|
|
@ -38,4 +38,4 @@ select_library_configurations(CRASHPAD_BASE)
|
||||||
select_library_configurations(CRASHPAD_UTIL)
|
select_library_configurations(CRASHPAD_UTIL)
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
find_package_handle_standard_args(CRASHPAD DEFAULT_MSG CRASHPAD_INCLUDE_DIRS CRASHPAD_LIBRARY CRASHPAD_BASE_LIBRARY CRASHPAD_UTIL_LIBRARY)
|
find_package_handle_standard_args(Crashpad DEFAULT_MSG CRASHPAD_INCLUDE_DIRS CRASHPAD_LIBRARY CRASHPAD_BASE_LIBRARY CRASHPAD_UTIL_LIBRARY)
|
||||||
|
|
|
@ -13,7 +13,10 @@
|
||||||
#define hifi_CrashHandler_h
|
#define hifi_CrashHandler_h
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
class QCoreApplication;
|
#include <QCoreApplication>
|
||||||
|
#include <QLoggingCategory>
|
||||||
|
|
||||||
|
Q_DECLARE_LOGGING_CATEGORY(crash_handler)
|
||||||
|
|
||||||
bool startCrashHandler(std::string appPath);
|
bool startCrashHandler(std::string appPath);
|
||||||
void setCrashAnnotation(std::string name, std::string value);
|
void setCrashAnnotation(std::string name, std::string value);
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
|
|
||||||
#include "CrashHandler.h"
|
#include "CrashHandler.h"
|
||||||
|
|
||||||
|
Q_LOGGING_CATEGORY(crash_handler, "vircadia.crash_handler")
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -141,6 +143,10 @@ static const QString CRASHPAD_HANDLER_NAME{ "crashpad_handler.exe" };
|
||||||
static const QString CRASHPAD_HANDLER_NAME{ "crashpad_handler" };
|
static const QString CRASHPAD_HANDLER_NAME{ "crashpad_handler" };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// The area within this #ifdef is specific to the Microsoft C++ compiler
|
// The area within this #ifdef is specific to the Microsoft C++ compiler
|
||||||
|
@ -311,8 +317,38 @@ void checkUnhandledExceptionHook() {
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
#endif // Q_OS_WIN
|
#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) {
|
bool startCrashHandler(std::string appPath) {
|
||||||
if (BACKTRACE_URL.empty() || BACKTRACE_TOKEN.empty()) {
|
if (BACKTRACE_URL.empty() || BACKTRACE_TOKEN.empty()) {
|
||||||
|
qCCritical(crash_handler) << "Backtrace URL or token not set, crash handler disabled.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,11 +374,29 @@ bool startCrashHandler(std::string appPath) {
|
||||||
const auto crashpadDbPath = crashpadDbDir.toStdString() + "/" + crashpadDbName;
|
const auto crashpadDbPath = crashpadDbDir.toStdString() + "/" + crashpadDbName;
|
||||||
|
|
||||||
// Locate Crashpad handler
|
// Locate Crashpad handler
|
||||||
const QFileInfo interfaceBinary{ QString::fromStdString(appPath) };
|
QString binaryDir = findBinaryDir();
|
||||||
const QDir interfaceDir = interfaceBinary.dir();
|
QDir interfaceDir;
|
||||||
assert(interfaceDir.exists(CRASHPAD_HANDLER_NAME));
|
|
||||||
|
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();
|
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
|
// Setup different file paths
|
||||||
base::FilePath::StringType dbPath;
|
base::FilePath::StringType dbPath;
|
||||||
base::FilePath::StringType handlerPath;
|
base::FilePath::StringType handlerPath;
|
||||||
|
@ -352,8 +406,10 @@ bool startCrashHandler(std::string appPath) {
|
||||||
base::FilePath db(dbPath);
|
base::FilePath db(dbPath);
|
||||||
base::FilePath handler(handlerPath);
|
base::FilePath handler(handlerPath);
|
||||||
|
|
||||||
|
qCDebug(crash_handler) << "Opening crashpad database" << QString::fromStdString(crashpadDbPath);
|
||||||
auto database = crashpad::CrashReportDatabase::Initialize(db);
|
auto database = crashpad::CrashReportDatabase::Initialize(db);
|
||||||
if (database == nullptr || database->GetSettings() == nullptr) {
|
if (database == nullptr || database->GetSettings() == nullptr) {
|
||||||
|
qCCritical(crash_handler) << "Failed to open crashpad database" << QString::fromStdString(crashpadDbPath);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,6 +417,7 @@ bool startCrashHandler(std::string appPath) {
|
||||||
database->GetSettings()->SetUploadsEnabled(true);
|
database->GetSettings()->SetUploadsEnabled(true);
|
||||||
|
|
||||||
if (!client->StartHandler(handler, db, db, BACKTRACE_URL, annotations, arguments, true, true)) {
|
if (!client->StartHandler(handler, db, db, BACKTRACE_URL, annotations, arguments, true, true)) {
|
||||||
|
qCCritical(crash_handler) << "Failed to start crashpad handler";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,6 +426,7 @@ bool startCrashHandler(std::string appPath) {
|
||||||
gl_crashpadUnhandledExceptionFilter = SetUnhandledExceptionFilter(unhandledExceptionHandler);
|
gl_crashpadUnhandledExceptionFilter = SetUnhandledExceptionFilter(unhandledExceptionHandler);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
qCInfo(crash_handler) << "Crashpad initialized";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,11 @@
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
|
|
||||||
|
Q_LOGGING_CATEGORY(crash_handler, "vircadia.crash_handler")
|
||||||
|
|
||||||
bool startCrashHandler(std::string appPath) {
|
bool startCrashHandler(std::string appPath) {
|
||||||
qDebug() << "No crash handler available.";
|
qCWarning(crash_handler) << "No crash handler available.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue