mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 02:57:10 +02:00
Merge pull request #12269 from sethalves/backtrace-for-rc-63
Backtrace for rc 63
This commit is contained in:
commit
215d03c4ce
25 changed files with 375 additions and 334 deletions
35
cmake/externals/crashpad/CMakeLists.txt
vendored
Normal file
35
cmake/externals/crashpad/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
include(ExternalProject)
|
||||||
|
set(EXTERNAL_NAME crashpad)
|
||||||
|
|
||||||
|
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
ExternalProject_Add(
|
||||||
|
${EXTERNAL_NAME}
|
||||||
|
URL https://backtrace.io/download/crashpad_062317.zip
|
||||||
|
URL_MD5 65817e564b3628492abfc1dbd2a1e98b
|
||||||
|
CONFIGURE_COMMAND ""
|
||||||
|
BUILD_COMMAND ""
|
||||||
|
INSTALL_COMMAND ""
|
||||||
|
LOG_DOWNLOAD 1
|
||||||
|
)
|
||||||
|
|
||||||
|
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
||||||
|
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE PATH "List of Crashpad include directories")
|
||||||
|
|
||||||
|
set(LIB_EXT "lib")
|
||||||
|
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${SOURCE_DIR}/out/Release_x64/lib_MD/${LIB_PREFIX}crashpad_client.${LIB_EXT} CACHE FILEPATH "Path to Crashpad release library")
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_BASE_LIBRARY_RELEASE ${SOURCE_DIR}/out/Release_x64/lib_MD/${LIB_PREFIX}base.${LIB_EXT} CACHE FILEPATH "Path to Crashpad base release library")
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_UTIL_LIBRARY_RELEASE ${SOURCE_DIR}/out/Release_x64/lib_MD/${LIB_PREFIX}crashpad_util.${LIB_EXT} CACHE FILEPATH "Path to Crashpad util release library")
|
||||||
|
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG ${SOURCE_DIR}/out/Debug_x64/lib_MD/${LIB_PREFIX}crashpad_client.${LIB_EXT} CACHE FILEPATH "Path to Crashpad debug library")
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_BASE_LIBRARY_DEBUG ${SOURCE_DIR}/out/Debug_x64/lib_MD/${LIB_PREFIX}base.${LIB_EXT} CACHE FILEPATH "Path to Crashpad base debug library")
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_UTIL_LIBRARY_DEBUG ${SOURCE_DIR}/out/Debug_x64/lib_MD/${LIB_PREFIX}crashpad_util.${LIB_EXT} CACHE FILEPATH "Path to Crashpad util debug library")
|
||||||
|
|
||||||
|
set(CRASHPAD_HANDLER_EXE_PATH ${SOURCE_DIR}/out/Release_x64/crashpad_handler.exe CACHE FILEPATH "Path to the Crashpad handler executable")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
# Hide this external target (for ide users)
|
||||||
|
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
|
@ -1,34 +0,0 @@
|
||||||
#
|
|
||||||
# AddBugSplat.cmake
|
|
||||||
# cmake/macros
|
|
||||||
#
|
|
||||||
# Created by Ryan Huffman on 02/09/16.
|
|
||||||
# Copyright 2016 High Fidelity, Inc.
|
|
||||||
#
|
|
||||||
# Distributed under the Apache License, Version 2.0.
|
|
||||||
# See the accompanying file LICENSE or http:#www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
#
|
|
||||||
|
|
||||||
macro(add_bugsplat)
|
|
||||||
get_property(BUGSPLAT_CHECKED GLOBAL PROPERTY CHECKED_FOR_BUGSPLAT_ONCE)
|
|
||||||
|
|
||||||
if (NOT BUGSPLAT_CHECKED)
|
|
||||||
find_package(BugSplat)
|
|
||||||
set_property(GLOBAL PROPERTY CHECKED_FOR_BUGSPLAT_ONCE TRUE)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (BUGSPLAT_FOUND)
|
|
||||||
add_definitions(-DHAS_BUGSPLAT)
|
|
||||||
|
|
||||||
target_include_directories(${TARGET_NAME} PRIVATE ${BUGSPLAT_INCLUDE_DIRS})
|
|
||||||
target_link_libraries(${TARGET_NAME} ${BUGSPLAT_LIBRARIES})
|
|
||||||
add_paths_to_fixup_libs(${BUGSPLAT_DLL_PATH})
|
|
||||||
|
|
||||||
add_custom_command(TARGET ${TARGET_NAME}
|
|
||||||
POST_BUILD
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${BUGSPLAT_RC_DLL_PATH} "$<TARGET_FILE_DIR:${TARGET_NAME}>/")
|
|
||||||
add_custom_command(TARGET ${TARGET_NAME}
|
|
||||||
POST_BUILD
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy ${BUGSPLAT_EXE_PATH} "$<TARGET_FILE_DIR:${TARGET_NAME}>/")
|
|
||||||
endif ()
|
|
||||||
endmacro()
|
|
58
cmake/macros/AddCrashpad.cmake
Normal file
58
cmake/macros/AddCrashpad.cmake
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
#
|
||||||
|
# AddCrashpad.cmake
|
||||||
|
# cmake/macros
|
||||||
|
#
|
||||||
|
# Created by Clement Brisset on 01/19/18.
|
||||||
|
# Copyright 2018 High Fidelity, Inc.
|
||||||
|
#
|
||||||
|
# Distributed under the Apache License, Version 2.0.
|
||||||
|
# See the accompanying file LICENSE or http:#www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
#
|
||||||
|
|
||||||
|
macro(add_crashpad)
|
||||||
|
set (USE_CRASHPAD TRUE)
|
||||||
|
if ("$ENV{CMAKE_BACKTRACE_URL}" STREQUAL "")
|
||||||
|
set(USE_CRASHPAD FALSE)
|
||||||
|
else()
|
||||||
|
set(CMAKE_BACKTRACE_URL $ENV{CMAKE_BACKTRACE_URL})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if ("$ENV{CMAKE_BACKTRACE_TOKEN}" STREQUAL "")
|
||||||
|
set(USE_CRASHPAD FALSE)
|
||||||
|
else()
|
||||||
|
set(CMAKE_BACKTRACE_TOKEN $ENV{CMAKE_BACKTRACE_TOKEN})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (WIN32 AND USE_CRASHPAD)
|
||||||
|
get_property(CRASHPAD_CHECKED GLOBAL PROPERTY CHECKED_FOR_CRASHPAD_ONCE)
|
||||||
|
if (NOT CRASHPAD_CHECKED)
|
||||||
|
|
||||||
|
add_dependency_external_projects(crashpad)
|
||||||
|
find_package(crashpad REQUIRED)
|
||||||
|
|
||||||
|
set_property(GLOBAL PROPERTY CHECKED_FOR_CRASHPAD_ONCE TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_definitions(-DHAS_CRASHPAD)
|
||||||
|
add_definitions(-DCMAKE_BACKTRACE_URL=\"${CMAKE_BACKTRACE_URL}\")
|
||||||
|
add_definitions(-DCMAKE_BACKTRACE_TOKEN=\"${CMAKE_BACKTRACE_TOKEN}\")
|
||||||
|
|
||||||
|
target_include_directories(${TARGET_NAME} PRIVATE ${CRASHPAD_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(${TARGET_NAME} ${CRASHPAD_LIBRARY} ${CRASHPAD_BASE_LIBRARY} ${CRASHPAD_UTIL_LIBRARY})
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS "/ignore:4099")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
TARGET ${TARGET_NAME}
|
||||||
|
POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy ${CRASHPAD_HANDLER_EXE_PATH} "$<TARGET_FILE_DIR:${TARGET_NAME}>/"
|
||||||
|
)
|
||||||
|
install(
|
||||||
|
PROGRAMS ${CRASHPAD_HANDLER_EXE_PATH}
|
||||||
|
DESTINATION ${CLIENT_COMPONENT}
|
||||||
|
COMPONENT ${INTERFACE_INSTALL_DIR}
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
endmacro()
|
|
@ -1,30 +0,0 @@
|
||||||
#
|
|
||||||
# FindBugSplat.cmake
|
|
||||||
# cmake/modules
|
|
||||||
#
|
|
||||||
# Created by Ryan Huffman on 02/09/16.
|
|
||||||
# Copyright 2016 High Fidelity, Inc.
|
|
||||||
#
|
|
||||||
# Distributed under the Apache License, Version 2.0.
|
|
||||||
# See the accompanying file LICENSE or http:#www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
#
|
|
||||||
|
|
||||||
if (WIN32)
|
|
||||||
include("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
|
|
||||||
hifi_library_search_hints("BugSplat")
|
|
||||||
|
|
||||||
find_path(BUGSPLAT_INCLUDE_DIRS NAMES BugSplat.h PATH_SUFFIXES inc HINTS ${BUGSPLAT_SEARCH_DIRS})
|
|
||||||
|
|
||||||
find_library(BUGSPLAT_LIBRARY_RELEASE "BugSplat64.lib" PATH_SUFFIXES "lib64" HINTS ${BUGSPLAT_SEARCH_DIRS})
|
|
||||||
find_path(BUGSPLAT_DLL_PATH NAMES "BugSplat64.dll" PATH_SUFFIXES "bin64" HINTS ${BUGSPLAT_SEARCH_DIRS})
|
|
||||||
find_file(BUGSPLAT_RC_DLL_PATH NAMES "BugSplatRc64.dll" PATH_SUFFIXES "bin64" HINTS ${BUGSPLAT_SEARCH_DIRS})
|
|
||||||
find_file(BUGSPLAT_EXE_PATH NAMES "BsSndRpt64.exe" PATH_SUFFIXES "bin64" HINTS ${BUGSPLAT_SEARCH_DIRS})
|
|
||||||
|
|
||||||
include(SelectLibraryConfigurations)
|
|
||||||
select_library_configurations(BUGSPLAT)
|
|
||||||
|
|
||||||
set(BUGSPLAT_LIBRARIES ${BUGSPLAT_LIBRARY_RELEASE})
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
set(BUGSPLAT_REQUIREMENTS BUGSPLAT_INCLUDE_DIRS BUGSPLAT_LIBRARIES BUGSPLAT_DLL_PATH BUGSPLAT_RC_DLL_PATH BUGSPLAT_EXE_PATH)
|
|
||||||
find_package_handle_standard_args(BugSplat DEFAULT_MSG ${BUGSPLAT_REQUIREMENTS})
|
|
41
cmake/modules/FindCrashpad.cmake
Normal file
41
cmake/modules/FindCrashpad.cmake
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#
|
||||||
|
# FindCrashpad.cmake
|
||||||
|
#
|
||||||
|
# Try to find Crashpad libraries and include path.
|
||||||
|
# Once done this will define
|
||||||
|
#
|
||||||
|
# CRASHPAD_FOUND
|
||||||
|
# CRASHPAD_INCLUDE_DIRS
|
||||||
|
# CRASHPAD_LIBRARY
|
||||||
|
# CRASHPAD_BASE_LIBRARY
|
||||||
|
# CRASHPAD_UTIL_LIBRARY
|
||||||
|
#
|
||||||
|
# Created on 01/19/2018 by Clement Brisset
|
||||||
|
# Copyright 2018 High Fidelity, Inc.
|
||||||
|
#
|
||||||
|
# Distributed under the Apache License, Version 2.0.
|
||||||
|
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
#
|
||||||
|
|
||||||
|
include("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
|
||||||
|
hifi_library_search_hints("crashpad")
|
||||||
|
|
||||||
|
find_path(CRASHPAD_INCLUDE_DIRS base/macros.h PATH_SUFFIXES include HINTS ${CRASHPAD_SEARCH_DIRS})
|
||||||
|
|
||||||
|
find_library(CRASHPAD_LIBRARY_RELEASE crashpad PATH_SUFFIXES "Release_x64/lib_MD" HINTS ${CRASHPAD_SEARCH_DIRS})
|
||||||
|
find_library(CRASHPAD_BASE_LIBRARY_RELEASE base PATH_SUFFIXES "Release_x64/lib_MD" HINTS ${CRASHPAD_SEARCH_DIRS})
|
||||||
|
find_library(CRASHPAD_UTIL_LIBRARY_RELEASE util PATH_SUFFIXES "Release_x64/lib_MD" HINTS ${CRASHPAD_SEARCH_DIRS})
|
||||||
|
|
||||||
|
find_library(CRASHPAD_LIBRARY_DEBUG crashpad PATH_SUFFIXES "Debug_x64/lib_MD" HINTS ${CRASHPAD_SEARCH_DIRS})
|
||||||
|
find_library(CRASHPAD_BASE_LIBRARY_DEBUG base PATH_SUFFIXES "Debug_x64/lib_MD" HINTS ${CRASHPAD_SEARCH_DIRS})
|
||||||
|
find_library(CRASHPAD_UTIL_LIBRARY_DEBUG util PATH_SUFFIXES "Debug_x64/lib_MD" HINTS ${CRASHPAD_SEARCH_DIRS})
|
||||||
|
|
||||||
|
find_file(CRASHPAD_HANDLER_EXE_PATH NAME "crashpad_handler.exe" PATH_SUFFIXES "Release_x64" HINTS ${CRASHPAD_SEARCH_DIRS})
|
||||||
|
|
||||||
|
include(SelectLibraryConfigurations)
|
||||||
|
select_library_configurations(CRASHPAD)
|
||||||
|
select_library_configurations(CRASHPAD_BASE)
|
||||||
|
select_library_configurations(CRASHPAD_UTIL)
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(CRASHPAD DEFAULT_MSG CRASHPAD_INCLUDE_DIRS CRASHPAD_LIBRARY CRASHPAD_BASE_LIBRARY CRASHPAD_UTIL_LIBRARY)
|
|
@ -157,7 +157,6 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
||||||
DependencyManager::set<StatTracker>();
|
DependencyManager::set<StatTracker>();
|
||||||
|
|
||||||
LogUtils::init();
|
LogUtils::init();
|
||||||
Setting::init();
|
|
||||||
|
|
||||||
qDebug() << "Setting up domain-server";
|
qDebug() << "Setting up domain-server";
|
||||||
qDebug() << "[VERSION] Build sequence:" << qPrintable(applicationVersion());
|
qDebug() << "[VERSION] Build sequence:" << qPrintable(applicationVersion());
|
||||||
|
|
|
@ -29,6 +29,8 @@ int main(int argc, char* argv[]) {
|
||||||
QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN);
|
QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN);
|
||||||
QCoreApplication::setApplicationVersion(BuildInfo::VERSION);
|
QCoreApplication::setApplicationVersion(BuildInfo::VERSION);
|
||||||
|
|
||||||
|
Setting::init();
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -216,6 +216,7 @@ target_include_directories(${TARGET_NAME} PRIVATE "${CMAKE_BINARY_DIR}/libraries
|
||||||
|
|
||||||
target_bullet()
|
target_bullet()
|
||||||
target_opengl()
|
target_opengl()
|
||||||
|
add_crashpad()
|
||||||
|
|
||||||
# perform standard include and linking for found externals
|
# perform standard include and linking for found externals
|
||||||
foreach(EXTERNAL ${OPTIONAL_EXTERNALS})
|
foreach(EXTERNAL ${OPTIONAL_EXTERNALS})
|
||||||
|
@ -347,8 +348,6 @@ if (SCRIPTS_INSTALL_DIR)
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_bugsplat()
|
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
set(EXTRA_DEPLOY_OPTIONS "--qmldir \"${PROJECT_SOURCE_DIR}/resources/qml\"")
|
set(EXTRA_DEPLOY_OPTIONS "--qmldir \"${PROJECT_SOURCE_DIR}/resources/qml\"")
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <glm/gtx/vector_angle.hpp>
|
#include <glm/gtx/vector_angle.hpp>
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
|
#include <QtCore/QResource>
|
||||||
#include <QtCore/QAbstractNativeEventFilter>
|
#include <QtCore/QAbstractNativeEventFilter>
|
||||||
#include <QtCore/QCommandLineParser>
|
#include <QtCore/QCommandLineParser>
|
||||||
#include <QtCore/QMimeData>
|
#include <QtCore/QMimeData>
|
||||||
|
@ -144,6 +145,7 @@
|
||||||
#include "avatar/AvatarManager.h"
|
#include "avatar/AvatarManager.h"
|
||||||
#include "avatar/MyHead.h"
|
#include "avatar/MyHead.h"
|
||||||
#include "CrashHandler.h"
|
#include "CrashHandler.h"
|
||||||
|
#include "Crashpad.h"
|
||||||
#include "devices/DdeFaceTracker.h"
|
#include "devices/DdeFaceTracker.h"
|
||||||
#include "DiscoverabilityManager.h"
|
#include "DiscoverabilityManager.h"
|
||||||
#include "GLCanvas.h"
|
#include "GLCanvas.h"
|
||||||
|
@ -612,8 +614,6 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
||||||
qApp->setProperty(hifi::properties::APP_LOCAL_DATA_PATH, cacheDir);
|
qApp->setProperty(hifi::properties::APP_LOCAL_DATA_PATH, cacheDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
Setting::init();
|
|
||||||
|
|
||||||
// Tell the plugin manager about our statically linked plugins
|
// Tell the plugin manager about our statically linked plugins
|
||||||
auto pluginManager = PluginManager::getInstance();
|
auto pluginManager = PluginManager::getInstance();
|
||||||
pluginManager->setInputPluginProvider([] { return getInputPlugins(); });
|
pluginManager->setInputPluginProvider([] { return getInputPlugins(); });
|
||||||
|
@ -861,6 +861,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
|
|
||||||
_logger->setSessionID(accountManager->getSessionID());
|
_logger->setSessionID(accountManager->getSessionID());
|
||||||
|
|
||||||
|
setCrashAnnotation("metaverse_session_id", accountManager->getSessionID().toString().toStdString());
|
||||||
|
|
||||||
if (steamClient) {
|
if (steamClient) {
|
||||||
qCDebug(interfaceapp) << "[VERSION] SteamVR buildID:" << steamClient->getSteamVRBuildID();
|
qCDebug(interfaceapp) << "[VERSION] SteamVR buildID:" << steamClient->getSteamVRBuildID();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,166 +0,0 @@
|
||||||
//
|
|
||||||
// CrashReporter.cpp
|
|
||||||
// interface/src
|
|
||||||
//
|
|
||||||
// Created by Ryan Huffman on 11 April 2016.
|
|
||||||
// Copyright 2016 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
#include "Application.h"
|
|
||||||
#include "CrashReporter.h"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <new.h>
|
|
||||||
#include <Windows.h>
|
|
||||||
#include <DbgHelp.h>
|
|
||||||
|
|
||||||
#include <csignal>
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
|
|
||||||
#pragma comment(lib, "Dbghelp.lib")
|
|
||||||
|
|
||||||
// SetUnhandledExceptionFilter can be overridden by the CRT at the point that an error occurs. More information
|
|
||||||
// can be found here: http://www.codeproject.com/Articles/154686/SetUnhandledExceptionFilter-and-the-C-C-Runtime-Li
|
|
||||||
// A fairly common approach is to patch the SetUnhandledExceptionFilter so that it cannot be overridden and so
|
|
||||||
// that the applicaiton can handle it itself.
|
|
||||||
// The CAPIHook class referenced in the above article is not openly available, but a similar implementation
|
|
||||||
// can be found here: http://blog.kalmbach-software.de/2008/04/02/unhandled-exceptions-in-vc8-and-above-for-x86-and-x64/
|
|
||||||
// The below has been adapted to work with different library and functions.
|
|
||||||
BOOL redirectLibraryFunctionToFunction(char* library, char* function, void* fn)
|
|
||||||
{
|
|
||||||
HMODULE lib = LoadLibrary(library);
|
|
||||||
if (lib == NULL) return FALSE;
|
|
||||||
void *pOrgEntry = GetProcAddress(lib, function);
|
|
||||||
if (pOrgEntry == NULL) return FALSE;
|
|
||||||
|
|
||||||
DWORD dwOldProtect = 0;
|
|
||||||
SIZE_T jmpSize = 5;
|
|
||||||
#ifdef _M_X64
|
|
||||||
jmpSize = 13;
|
|
||||||
#endif
|
|
||||||
BOOL bProt = VirtualProtect(pOrgEntry, jmpSize,
|
|
||||||
PAGE_EXECUTE_READWRITE, &dwOldProtect);
|
|
||||||
BYTE newJump[20];
|
|
||||||
void *pNewFunc = fn;
|
|
||||||
#ifdef _M_IX86
|
|
||||||
DWORD dwOrgEntryAddr = (DWORD)pOrgEntry;
|
|
||||||
dwOrgEntryAddr += jmpSize; // add 5 for 5 op-codes for jmp rel32
|
|
||||||
DWORD dwNewEntryAddr = (DWORD)pNewFunc;
|
|
||||||
DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr;
|
|
||||||
// JMP rel32: Jump near, relative, displacement relative to next instruction.
|
|
||||||
newJump[0] = 0xE9; // JMP rel32
|
|
||||||
memcpy(&newJump[1], &dwRelativeAddr, sizeof(pNewFunc));
|
|
||||||
#elif _M_X64
|
|
||||||
// We must use R10 or R11, because these are "scratch" registers
|
|
||||||
// which need not to be preserved accross function calls
|
|
||||||
// For more info see: Register Usage for x64 64-Bit
|
|
||||||
// http://msdn.microsoft.com/en-us/library/ms794547.aspx
|
|
||||||
// Thanks to Matthew Smith!!!
|
|
||||||
newJump[0] = 0x49; // MOV R11, ...
|
|
||||||
newJump[1] = 0xBB; // ...
|
|
||||||
memcpy(&newJump[2], &pNewFunc, sizeof(pNewFunc));
|
|
||||||
//pCur += sizeof (ULONG_PTR);
|
|
||||||
newJump[10] = 0x41; // JMP R11, ...
|
|
||||||
newJump[11] = 0xFF; // ...
|
|
||||||
newJump[12] = 0xE3; // ...
|
|
||||||
#endif
|
|
||||||
SIZE_T bytesWritten;
|
|
||||||
BOOL bRet = WriteProcessMemory(GetCurrentProcess(),
|
|
||||||
pOrgEntry, newJump, jmpSize, &bytesWritten);
|
|
||||||
|
|
||||||
if (bProt != FALSE)
|
|
||||||
{
|
|
||||||
DWORD dwBuf;
|
|
||||||
VirtualProtect(pOrgEntry, jmpSize, dwOldProtect, &dwBuf);
|
|
||||||
}
|
|
||||||
return bRet;
|
|
||||||
}
|
|
||||||
|
|
||||||
void printStackTrace(ULONG framesToSkip = 1) {
|
|
||||||
HANDLE process = GetCurrentProcess();
|
|
||||||
SymInitialize(process, NULL, TRUE);
|
|
||||||
void* stack[100];
|
|
||||||
uint16_t frames = CaptureStackBackTrace(framesToSkip, 100, stack, NULL);
|
|
||||||
SYMBOL_INFO* symbol = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);
|
|
||||||
symbol->MaxNameLen = 255;
|
|
||||||
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
|
||||||
|
|
||||||
for (uint16_t i = 0; i < frames; ++i) {
|
|
||||||
SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol);
|
|
||||||
qWarning() << QString("%1: %2 - 0x%0X").arg(QString::number(frames - i - 1), QString(symbol->Name), QString::number(symbol->Address, 16));
|
|
||||||
}
|
|
||||||
|
|
||||||
free(symbol);
|
|
||||||
|
|
||||||
// Try to force the log to sync to the filesystem
|
|
||||||
auto app = qApp;
|
|
||||||
if (app && app->getLogger()) {
|
|
||||||
app->getLogger()->sync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void handleSignal(int signal) {
|
|
||||||
// Throw so BugSplat can handle
|
|
||||||
throw(signal);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __cdecl handlePureVirtualCall() {
|
|
||||||
qWarning() << "Pure virtual function call detected";
|
|
||||||
printStackTrace(2);
|
|
||||||
// Throw so BugSplat can handle
|
|
||||||
throw("ERROR: Pure virtual call");
|
|
||||||
}
|
|
||||||
|
|
||||||
void handleInvalidParameter(const wchar_t * expression, const wchar_t * function, const wchar_t * file,
|
|
||||||
unsigned int line, uintptr_t pReserved ) {
|
|
||||||
// Throw so BugSplat can handle
|
|
||||||
throw("ERROR: Invalid parameter");
|
|
||||||
}
|
|
||||||
|
|
||||||
int handleNewError(size_t size) {
|
|
||||||
// Throw so BugSplat can handle
|
|
||||||
throw("ERROR: Errors calling new");
|
|
||||||
}
|
|
||||||
|
|
||||||
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI noop_SetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
_purecall_handler __cdecl noop_set_purecall_handler(_purecall_handler pNew) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAS_BUGSPLAT
|
|
||||||
|
|
||||||
static const DWORD BUG_SPLAT_FLAGS = MDSF_PREVENTHIJACKING | MDSF_USEGUARDMEMORY;
|
|
||||||
|
|
||||||
CrashReporter::CrashReporter(QString bugSplatDatabase, QString bugSplatApplicationName, QString version)
|
|
||||||
: mpSender(qPrintable(bugSplatDatabase), qPrintable(bugSplatApplicationName), qPrintable(version), nullptr, BUG_SPLAT_FLAGS)
|
|
||||||
{
|
|
||||||
signal(SIGSEGV, handleSignal);
|
|
||||||
signal(SIGABRT, handleSignal);
|
|
||||||
_set_purecall_handler(handlePureVirtualCall);
|
|
||||||
_set_invalid_parameter_handler(handleInvalidParameter);
|
|
||||||
_set_new_mode(1);
|
|
||||||
_set_new_handler(handleNewError);
|
|
||||||
|
|
||||||
// Disable WER popup
|
|
||||||
//SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
|
|
||||||
//_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
|
|
||||||
|
|
||||||
// QtWebEngineCore internally sets its own purecall handler, overriding our own error handling. This disables that.
|
|
||||||
if (!redirectLibraryFunctionToFunction("msvcr120.dll", "_set_purecall_handler", &noop_set_purecall_handler)) {
|
|
||||||
qWarning() << "Failed to patch _set_purecall_handler";
|
|
||||||
}
|
|
||||||
// Patch SetUnhandledExceptionFilter to keep the CRT from overriding our own error handling.
|
|
||||||
if (!redirectLibraryFunctionToFunction("kernel32.dll", "SetUnhandledExceptionFilter", &noop_SetUnhandledExceptionFilter)) {
|
|
||||||
qWarning() << "Failed to patch setUnhandledExceptionFilter";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
|
@ -1,32 +0,0 @@
|
||||||
//
|
|
||||||
// CrashReporter.h
|
|
||||||
// interface/src
|
|
||||||
//
|
|
||||||
// Created by Ryan Huffman on 11 April 2016.
|
|
||||||
// Copyright 2016 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifndef hifi_CrashReporter_h
|
|
||||||
#define hifi_CrashReporter_h
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
#ifdef HAS_BUGSPLAT
|
|
||||||
|
|
||||||
#include <BugSplat.h>
|
|
||||||
|
|
||||||
class CrashReporter {
|
|
||||||
public:
|
|
||||||
CrashReporter(QString bugSplatDatabase, QString bugSplatApplicationName, QString version);
|
|
||||||
|
|
||||||
MiniDmpSender mpSender;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // hifi_CrashReporter_h
|
|
101
interface/src/Crashpad.cpp
Normal file
101
interface/src/Crashpad.cpp
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
//
|
||||||
|
// Crashpad.cpp
|
||||||
|
// interface/src
|
||||||
|
//
|
||||||
|
// Created by Clement Brisset on 01/19/18.
|
||||||
|
// Copyright 2018 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Crashpad.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
#if HAS_CRASHPAD
|
||||||
|
|
||||||
|
#include <QStandardPaths>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
|
#include <BuildInfo.h>
|
||||||
|
|
||||||
|
#include <client/crashpad_client.h>
|
||||||
|
#include <client/crash_report_database.h>
|
||||||
|
#include <client/settings.h>
|
||||||
|
// #include <client/annotation_list.h>
|
||||||
|
// #include <client/crashpad_info.h>
|
||||||
|
|
||||||
|
using namespace crashpad;
|
||||||
|
|
||||||
|
static const std::string BACKTRACE_URL { CMAKE_BACKTRACE_URL };
|
||||||
|
static const std::string BACKTRACE_TOKEN { CMAKE_BACKTRACE_TOKEN };
|
||||||
|
|
||||||
|
extern QString qAppFileName();
|
||||||
|
|
||||||
|
// crashpad::AnnotationList* crashpadAnnotations { nullptr };
|
||||||
|
|
||||||
|
bool startCrashHandler() {
|
||||||
|
if (BACKTRACE_URL.empty() || BACKTRACE_TOKEN.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CrashpadClient client;
|
||||||
|
std::vector<std::string> arguments;
|
||||||
|
|
||||||
|
std::map<std::string, std::string> annotations;
|
||||||
|
annotations["token"] = BACKTRACE_TOKEN;
|
||||||
|
annotations["format"] = "minidump";
|
||||||
|
annotations["version"] = BuildInfo::VERSION.toStdString();
|
||||||
|
|
||||||
|
arguments.push_back("--no-rate-limit");
|
||||||
|
|
||||||
|
// Setup Crashpad DB directory
|
||||||
|
const auto crashpadDbName = "crashpad-db";
|
||||||
|
const auto crashpadDbDir = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
|
||||||
|
QDir(crashpadDbDir).mkpath(crashpadDbName); // Make sure the directory exists
|
||||||
|
const auto crashpadDbPath = crashpadDbDir.toStdString() + "/" + crashpadDbName;
|
||||||
|
|
||||||
|
// Locate Crashpad handler
|
||||||
|
const std::string CRASHPAD_HANDLER_PATH = QFileInfo(qAppFileName()).absolutePath().toStdString() + "/crashpad_handler.exe";
|
||||||
|
|
||||||
|
// Setup different file paths
|
||||||
|
base::FilePath::StringType dbPath;
|
||||||
|
base::FilePath::StringType handlerPath;
|
||||||
|
dbPath.assign(crashpadDbPath.cbegin(), crashpadDbPath.cend());
|
||||||
|
handlerPath.assign(CRASHPAD_HANDLER_PATH.cbegin(), CRASHPAD_HANDLER_PATH.cend());
|
||||||
|
|
||||||
|
base::FilePath db(dbPath);
|
||||||
|
base::FilePath handler(handlerPath);
|
||||||
|
|
||||||
|
auto database = crashpad::CrashReportDatabase::Initialize(db);
|
||||||
|
if (database == nullptr || database->GetSettings() == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable automated uploads.
|
||||||
|
database->GetSettings()->SetUploadsEnabled(true);
|
||||||
|
|
||||||
|
return client.StartHandler(handler, db, db, BACKTRACE_URL, annotations, arguments, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setCrashAnnotation(std::string name, std::string value) {
|
||||||
|
// if (!crashpadAnnotations) {
|
||||||
|
// crashpadAnnotations = new crashpad::AnnotationList(); // don't free this, let it leak
|
||||||
|
// crashpad::CrashpadInfo* crashpad_info = crashpad::GetCrashpadInfo();
|
||||||
|
// crashpad_info->set_simple_annotations(crashpadAnnotations);
|
||||||
|
// }
|
||||||
|
// crashpadAnnotations->SetKeyValue(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
bool startCrashHandler() {
|
||||||
|
qDebug() << "No crash handler available.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setCrashAnnotation(std::string name, std::string value) {
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
20
interface/src/Crashpad.h
Normal file
20
interface/src/Crashpad.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
//
|
||||||
|
// Crashpad.h
|
||||||
|
// interface/src
|
||||||
|
//
|
||||||
|
// Created by Clement Brisset on 01/19/18.
|
||||||
|
// Copyright 2018 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi_Crashpad_h
|
||||||
|
#define hifi_Crashpad_h
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
bool startCrashHandler();
|
||||||
|
void setCrashAnnotation(std::string name, std::string value);
|
||||||
|
|
||||||
|
#endif // hifi_Crashpad_h
|
|
@ -27,15 +27,11 @@
|
||||||
|
|
||||||
#include "AddressManager.h"
|
#include "AddressManager.h"
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
#include "Crashpad.h"
|
||||||
#include "InterfaceLogging.h"
|
#include "InterfaceLogging.h"
|
||||||
#include "UserActivityLogger.h"
|
#include "UserActivityLogger.h"
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
|
|
||||||
#ifdef HAS_BUGSPLAT
|
|
||||||
#include <BugSplat.h>
|
|
||||||
#include <CrashReporter.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
extern "C" {
|
extern "C" {
|
||||||
typedef int(__stdcall * CHECKMINSPECPROC) ();
|
typedef int(__stdcall * CHECKMINSPECPROC) ();
|
||||||
|
@ -43,11 +39,6 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
#if HAS_BUGSPLAT
|
|
||||||
static QString BUG_SPLAT_DATABASE = "interface_alpha";
|
|
||||||
static QString BUG_SPLAT_APPLICATION_NAME = "Interface";
|
|
||||||
CrashReporter crashReporter { BUG_SPLAT_DATABASE, BUG_SPLAT_APPLICATION_NAME, BuildInfo::VERSION };
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
|
QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
|
||||||
|
@ -64,6 +55,17 @@ int main(int argc, const char* argv[]) {
|
||||||
QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN);
|
QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN);
|
||||||
QCoreApplication::setApplicationVersion(BuildInfo::VERSION);
|
QCoreApplication::setApplicationVersion(BuildInfo::VERSION);
|
||||||
|
|
||||||
|
Setting::init();
|
||||||
|
|
||||||
|
// Instance UserActivityLogger now that the settings are loaded
|
||||||
|
auto& ual = UserActivityLogger::getInstance();
|
||||||
|
qDebug() << "UserActivityLogger is enabled:" << ual.isEnabled();
|
||||||
|
|
||||||
|
if (ual.isEnabled()) {
|
||||||
|
auto crashHandlerStarted = startCrashHandler();
|
||||||
|
qDebug() << "Crash handler started:" << crashHandlerStarted;
|
||||||
|
}
|
||||||
|
|
||||||
QStringList arguments;
|
QStringList arguments;
|
||||||
for (int i = 0; i < argc; ++i) {
|
for (int i = 0; i < argc; ++i) {
|
||||||
arguments << argv[i];
|
arguments << argv[i];
|
||||||
|
@ -253,7 +255,6 @@ int main(int argc, const char* argv[]) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Setup local server
|
// Setup local server
|
||||||
QLocalServer server { &app };
|
QLocalServer server { &app };
|
||||||
|
|
||||||
|
@ -261,29 +262,8 @@ int main(int argc, const char* argv[]) {
|
||||||
server.removeServer(applicationName);
|
server.removeServer(applicationName);
|
||||||
server.listen(applicationName);
|
server.listen(applicationName);
|
||||||
|
|
||||||
QObject::connect(&server, &QLocalServer::newConnection, &app, &Application::handleLocalServerConnection, Qt::DirectConnection);
|
QObject::connect(&server, &QLocalServer::newConnection,
|
||||||
|
&app, &Application::handleLocalServerConnection, Qt::DirectConnection);
|
||||||
#ifdef HAS_BUGSPLAT
|
|
||||||
auto accountManager = DependencyManager::get<AccountManager>();
|
|
||||||
crashReporter.mpSender.setDefaultUserName(qPrintable(accountManager->getAccountInfo().getUsername()));
|
|
||||||
QObject::connect(accountManager.data(), &AccountManager::usernameChanged, &app, [&crashReporter](const QString& newUsername) {
|
|
||||||
crashReporter.mpSender.setDefaultUserName(qPrintable(newUsername));
|
|
||||||
});
|
|
||||||
|
|
||||||
// BugSplat WILL NOT work with file paths that do not use OS native separators.
|
|
||||||
auto logger = app.getLogger();
|
|
||||||
auto logPath = QDir::toNativeSeparators(logger->getFilename());
|
|
||||||
crashReporter.mpSender.sendAdditionalFile(qPrintable(logPath));
|
|
||||||
|
|
||||||
QMetaObject::Connection connection;
|
|
||||||
connection = QObject::connect(logger, &FileLogger::rollingLogFile, &app, [&crashReporter, &connection](QString newFilename) {
|
|
||||||
// We only want to add the first rolled log file (the "beginning" of the log) to BugSplat to ensure we don't exceed the 2MB
|
|
||||||
// zipped limit, so we disconnect here.
|
|
||||||
QObject::disconnect(connection);
|
|
||||||
auto rolledLogPath = QDir::toNativeSeparators(newFilename);
|
|
||||||
crashReporter.mpSender.sendAdditionalFile(qPrintable(rolledLogPath));
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
|
|
||||||
printSystemInformation();
|
printSystemInformation();
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "SettingHelpers.h"
|
#include "SettingHelpers.h"
|
||||||
#include "SettingManager.h"
|
#include "SettingManager.h"
|
||||||
#include "SharedLogging.h"
|
#include "SharedLogging.h"
|
||||||
|
#include "SharedUtil.h"
|
||||||
|
|
||||||
namespace Setting {
|
namespace Setting {
|
||||||
static QSharedPointer<Manager> globalManager;
|
static QSharedPointer<Manager> globalManager;
|
||||||
|
@ -32,7 +33,6 @@ namespace Setting {
|
||||||
// tell the private instance to clean itself up on its thread
|
// tell the private instance to clean itself up on its thread
|
||||||
DependencyManager::destroy<Manager>();
|
DependencyManager::destroy<Manager>();
|
||||||
|
|
||||||
//
|
|
||||||
globalManager.reset();
|
globalManager.reset();
|
||||||
|
|
||||||
// quit the settings manager thread and wait on it to make sure it's gone
|
// quit the settings manager thread and wait on it to make sure it's gone
|
||||||
|
@ -40,6 +40,27 @@ namespace Setting {
|
||||||
settingsManagerThread->wait();
|
settingsManagerThread->wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setupPrivateInstance() {
|
||||||
|
// Ensure Setting::init has already ran and qApp exists
|
||||||
|
if (qApp && globalManager) {
|
||||||
|
// Let's set up the settings Private instance on its own thread
|
||||||
|
QThread* thread = new QThread();
|
||||||
|
Q_CHECK_PTR(thread);
|
||||||
|
thread->setObjectName("Settings Thread");
|
||||||
|
|
||||||
|
QObject::connect(thread, SIGNAL(started()), globalManager.data(), SLOT(startTimer()));
|
||||||
|
QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
|
||||||
|
QObject::connect(thread, SIGNAL(finished()), globalManager.data(), SLOT(deleteLater()));
|
||||||
|
globalManager->moveToThread(thread);
|
||||||
|
thread->start();
|
||||||
|
qCDebug(shared) << "Settings thread started.";
|
||||||
|
|
||||||
|
// Register cleanupPrivateInstance to run inside QCoreApplication's destructor.
|
||||||
|
qAddPostRoutine(cleanupPrivateInstance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FIXED_Q_COREAPP_STARTUP_FUNCTION(setupPrivateInstance)
|
||||||
|
|
||||||
// Sets up the settings private instance. Should only be run once at startup. preInit() must be run beforehand,
|
// Sets up the settings private instance. Should only be run once at startup. preInit() must be run beforehand,
|
||||||
void init() {
|
void init() {
|
||||||
// Set settings format
|
// Set settings format
|
||||||
|
@ -59,23 +80,9 @@ namespace Setting {
|
||||||
qCDebug(shared) << (deleted ? "Deleted" : "Failed to delete") << "settings lock file" << settingsLockFilename;
|
qCDebug(shared) << (deleted ? "Deleted" : "Failed to delete") << "settings lock file" << settingsLockFilename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Let's set up the settings Private instance on its own thread
|
|
||||||
QThread* thread = new QThread();
|
|
||||||
Q_CHECK_PTR(thread);
|
|
||||||
thread->setObjectName("Settings Thread");
|
|
||||||
|
|
||||||
globalManager = DependencyManager::set<Manager>();
|
globalManager = DependencyManager::set<Manager>();
|
||||||
|
|
||||||
QObject::connect(thread, SIGNAL(started()), globalManager.data(), SLOT(startTimer()));
|
setupPrivateInstance();
|
||||||
QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
|
|
||||||
QObject::connect(thread, SIGNAL(finished()), globalManager.data(), SLOT(deleteLater()));
|
|
||||||
globalManager->moveToThread(thread);
|
|
||||||
thread->start();
|
|
||||||
qCDebug(shared) << "Settings thread started.";
|
|
||||||
|
|
||||||
// Register cleanupPrivateInstance to run inside QCoreApplication's destructor.
|
|
||||||
qAddPostRoutine(cleanupPrivateInstance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::init() {
|
void Interface::init() {
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
@ -62,6 +63,43 @@ extern "C" FILE * __cdecl __iob_func(void) {
|
||||||
#include "OctalCode.h"
|
#include "OctalCode.h"
|
||||||
#include "SharedLogging.h"
|
#include "SharedLogging.h"
|
||||||
|
|
||||||
|
static std::unordered_map<std::string, QVariant> stagedGlobalInstances;
|
||||||
|
|
||||||
|
|
||||||
|
std::mutex& globalInstancesMutex() {
|
||||||
|
static std::mutex mutex;
|
||||||
|
return mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void commitGlobalInstances() {
|
||||||
|
std::unique_lock<std::mutex> lock(globalInstancesMutex());
|
||||||
|
for (const auto& it : stagedGlobalInstances) {
|
||||||
|
qApp->setProperty(it.first.c_str(), it.second);
|
||||||
|
}
|
||||||
|
stagedGlobalInstances.clear();
|
||||||
|
}
|
||||||
|
FIXED_Q_COREAPP_STARTUP_FUNCTION(commitGlobalInstances)
|
||||||
|
|
||||||
|
QVariant getGlobalInstance(const char* propertyName) {
|
||||||
|
if (qApp) {
|
||||||
|
return qApp->property(propertyName);
|
||||||
|
} else {
|
||||||
|
auto it = stagedGlobalInstances.find(propertyName);
|
||||||
|
if (it != stagedGlobalInstances.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setGlobalInstance(const char* propertyName, const QVariant& variant) {
|
||||||
|
if (qApp) {
|
||||||
|
qApp->setProperty(propertyName, variant);
|
||||||
|
} else {
|
||||||
|
stagedGlobalInstances[propertyName] = variant;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static qint64 usecTimestampNowAdjust = 0; // in usec
|
static qint64 usecTimestampNowAdjust = 0; // in usec
|
||||||
void usecTimestampNowForceClockSkew(qint64 clockSkew) {
|
void usecTimestampNowForceClockSkew(qint64 clockSkew) {
|
||||||
::usecTimestampNowAdjust = clockSkew;
|
::usecTimestampNowAdjust = clockSkew;
|
||||||
|
|
|
@ -25,6 +25,22 @@
|
||||||
#include <QtCore/QCoreApplication>
|
#include <QtCore/QCoreApplication>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
|
// Workaround for https://bugreports.qt.io/browse/QTBUG-54479
|
||||||
|
// Wrap target function inside another function that holds
|
||||||
|
// a unique string identifier and uses it to ensure it only runs once
|
||||||
|
// by storing a state within the qApp
|
||||||
|
// We cannot used std::call_once with a static once_flag because
|
||||||
|
// this is used in shared libraries that are linked by several DLLs
|
||||||
|
// (ie. plugins), meaning the static will be useless in that case
|
||||||
|
#define FIXED_Q_COREAPP_STARTUP_FUNCTION(AFUNC) \
|
||||||
|
static void AFUNC ## _fixed() { \
|
||||||
|
const auto propertyName = std::string(Q_FUNC_INFO) + __FILE__; \
|
||||||
|
if (!qApp->property(propertyName.c_str()).toBool()) { \
|
||||||
|
AFUNC(); \
|
||||||
|
qApp->setProperty(propertyName.c_str(), QVariant(true)); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
Q_COREAPP_STARTUP_FUNCTION(AFUNC ## _fixed)
|
||||||
|
|
||||||
// When writing out avatarEntities to a QByteArray, if the parentID is the ID of MyAvatar, use this ID instead. This allows
|
// When writing out avatarEntities to a QByteArray, if the parentID is the ID of MyAvatar, use this ID instead. This allows
|
||||||
// the value to be reset when the sessionID changes.
|
// the value to be reset when the sessionID changes.
|
||||||
|
@ -52,6 +68,10 @@ bool destroyGlobalInstance() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::mutex& globalInstancesMutex();
|
||||||
|
QVariant getGlobalInstance(const char* propertyName);
|
||||||
|
void setGlobalInstance(const char* propertyName, const QVariant& variant);
|
||||||
|
|
||||||
// Provides efficient access to a named global type. By storing the value
|
// Provides efficient access to a named global type. By storing the value
|
||||||
// in the QApplication by name we can implement the singleton pattern and
|
// in the QApplication by name we can implement the singleton pattern and
|
||||||
// have the single instance function across DLL boundaries.
|
// have the single instance function across DLL boundaries.
|
||||||
|
@ -60,9 +80,9 @@ T* globalInstance(const char* propertyName, Args&&... args) {
|
||||||
static T* resultInstance { nullptr };
|
static T* resultInstance { nullptr };
|
||||||
static std::mutex mutex;
|
static std::mutex mutex;
|
||||||
if (!resultInstance) {
|
if (!resultInstance) {
|
||||||
std::unique_lock<std::mutex> lock(mutex);
|
std::unique_lock<std::mutex> lock(globalInstancesMutex());
|
||||||
if (!resultInstance) {
|
if (!resultInstance) {
|
||||||
auto variant = qApp->property(propertyName);
|
auto variant = getGlobalInstance(propertyName);
|
||||||
if (variant.isNull()) {
|
if (variant.isNull()) {
|
||||||
std::unique_ptr<T>& instancePtr = globalInstancePointer<T>();
|
std::unique_ptr<T>& instancePtr = globalInstancePointer<T>();
|
||||||
if (!instancePtr.get()) {
|
if (!instancePtr.get()) {
|
||||||
|
@ -72,7 +92,7 @@ T* globalInstance(const char* propertyName, Args&&... args) {
|
||||||
}
|
}
|
||||||
void* voidInstance = &(*instancePtr);
|
void* voidInstance = &(*instancePtr);
|
||||||
variant = QVariant::fromValue(voidInstance);
|
variant = QVariant::fromValue(voidInstance);
|
||||||
qApp->setProperty(propertyName, variant);
|
setGlobalInstance(propertyName, variant);
|
||||||
}
|
}
|
||||||
void* returnedVoidInstance = variant.value<void*>();
|
void* returnedVoidInstance = variant.value<void*>();
|
||||||
resultInstance = static_cast<T*>(returnedVoidInstance);
|
resultInstance = static_cast<T*>(returnedVoidInstance);
|
||||||
|
|
|
@ -33,8 +33,6 @@ private:
|
||||||
Qt59TestApp::Qt59TestApp(int argc, char* argv[]) :
|
Qt59TestApp::Qt59TestApp(int argc, char* argv[]) :
|
||||||
QCoreApplication(argc, argv)
|
QCoreApplication(argc, argv)
|
||||||
{
|
{
|
||||||
|
|
||||||
Setting::init();
|
|
||||||
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
|
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
|
||||||
DependencyManager::set<AccountManager>([&] { return QString("Mozilla/5.0 (HighFidelityACClient)"); });
|
DependencyManager::set<AccountManager>([&] { return QString("Mozilla/5.0 (HighFidelityACClient)"); });
|
||||||
DependencyManager::set<AddressManager>();
|
DependencyManager::set<AddressManager>();
|
||||||
|
|
|
@ -97,7 +97,6 @@ ACClientApp::ACClientApp(int argc, char* argv[]) :
|
||||||
_password = pieces[1];
|
_password = pieces[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
Setting::init();
|
|
||||||
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
|
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
|
||||||
|
|
||||||
DependencyManager::set<AccountManager>([&]{ return QString("Mozilla/5.0 (HighFidelityACClient)"); });
|
DependencyManager::set<AccountManager>([&]{ return QString("Mozilla/5.0 (HighFidelityACClient)"); });
|
||||||
|
|
|
@ -25,6 +25,8 @@ int main(int argc, char * argv[]) {
|
||||||
QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN);
|
QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN);
|
||||||
QCoreApplication::setApplicationVersion(BuildInfo::VERSION);
|
QCoreApplication::setApplicationVersion(BuildInfo::VERSION);
|
||||||
|
|
||||||
|
Setting::init();
|
||||||
|
|
||||||
ACClientApp app(argc, argv);
|
ACClientApp app(argc, argv);
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
|
|
|
@ -135,7 +135,6 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) :
|
||||||
_domainServerAddress = domainURL.toString();
|
_domainServerAddress = domainURL.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
Setting::init();
|
|
||||||
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
|
DependencyManager::registerInheritance<LimitedNodeList, NodeList>();
|
||||||
|
|
||||||
DependencyManager::set<StatTracker>();
|
DependencyManager::set<StatTracker>();
|
||||||
|
|
|
@ -25,6 +25,8 @@ int main(int argc, char * argv[]) {
|
||||||
QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN);
|
QCoreApplication::setOrganizationDomain(BuildInfo::ORGANIZATION_DOMAIN);
|
||||||
QCoreApplication::setApplicationVersion(BuildInfo::VERSION);
|
QCoreApplication::setApplicationVersion(BuildInfo::VERSION);
|
||||||
|
|
||||||
|
Setting::init();
|
||||||
|
|
||||||
ATPClientApp app(argc, argv);
|
ATPClientApp app(argc, argv);
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include <QtCore/QCommandLineParser>
|
#include <QtCore/QCommandLineParser>
|
||||||
|
|
||||||
#include <image/Image.h>
|
#include <image/Image.h>
|
||||||
#include <SettingInterface.h>
|
|
||||||
|
|
||||||
#include "ui/OvenMainWindow.h"
|
#include "ui/OvenMainWindow.h"
|
||||||
#include "Oven.h"
|
#include "Oven.h"
|
||||||
|
@ -29,12 +28,6 @@ static const QString CLI_TYPE_PARAMETER = "t";
|
||||||
Oven::Oven(int argc, char* argv[]) :
|
Oven::Oven(int argc, char* argv[]) :
|
||||||
QApplication(argc, argv)
|
QApplication(argc, argv)
|
||||||
{
|
{
|
||||||
QCoreApplication::setOrganizationName("High Fidelity");
|
|
||||||
QCoreApplication::setApplicationName("Oven");
|
|
||||||
|
|
||||||
// init the settings interface so we can save and load settings
|
|
||||||
Setting::init();
|
|
||||||
|
|
||||||
// parse the command line parameters
|
// parse the command line parameters
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,15 @@
|
||||||
|
|
||||||
#include "Oven.h"
|
#include "Oven.h"
|
||||||
|
|
||||||
|
#include <SettingInterface.h>
|
||||||
|
|
||||||
int main (int argc, char** argv) {
|
int main (int argc, char** argv) {
|
||||||
|
QCoreApplication::setOrganizationName("High Fidelity");
|
||||||
|
QCoreApplication::setApplicationName("Oven");
|
||||||
|
|
||||||
|
// init the settings interface so we can save and load settings
|
||||||
|
Setting::init();
|
||||||
|
|
||||||
Oven app(argc, argv);
|
Oven app(argc, argv);
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue