Crash reporter moved to separate library

UAL moved back to networking
This commit is contained in:
Dale Glass 2023-06-26 00:21:14 +02:00
parent 6ec276c818
commit 4dcc2882fd
16 changed files with 339 additions and 308 deletions

View file

@ -230,7 +230,7 @@ link_hifi_libraries(
${PLATFORM_GL_BACKEND}
# Plaform specific input & display plugin libraries
${PLATFORM_PLUGIN_LIBRARIES}
shaders
shaders monitoring
)
include_hifi_library_headers(script-engine)

View file

@ -179,7 +179,7 @@
#include "avatar/AvatarPackager.h"
#include "avatar/MyCharacterController.h"
#include "CrashRecoveryHandler.h"
#include "CrashHandler.h"
#include "crash-handler/CrashHandler.h"
#include "DiscoverabilityManager.h"
#include "GLCanvas.h"
#include "InterfaceDynamicFactory.h"
@ -407,8 +407,10 @@ public:
}
void deadlockDetectionCrash() {
setCrashAnnotation("_mod_faulting_tid", std::to_string((uint64_t)_mainThreadID));
setCrashAnnotation("deadlock", "1");
auto &ch = CrashHandler::getInstance();
ch.setAnnotation("_mod_faulting_tid", std::to_string((uint64_t)_mainThreadID));
ch.setAnnotation("deadlock", "1");
uint32_t* crashTrigger = nullptr;
*crashTrigger = 0xDEAD10CC;
}
@ -1054,9 +1056,11 @@ Application::Application(
{
// identify gpu as early as possible to help identify OpenGL initialization errors.
auto gpuIdent = GPUIdent::getInstance();
setCrashAnnotation("sentry[contexts][gpu][name]", gpuIdent->getName().toStdString());
setCrashAnnotation("sentry[contexts][gpu][version]", gpuIdent->getDriver().toStdString());
setCrashAnnotation("gpu_memory", std::to_string(gpuIdent->getMemory()));
auto &ch = CrashHandler::getInstance();
ch.setAnnotation("sentry[contexts][gpu][name]", gpuIdent->getName().toStdString());
ch.setAnnotation("sentry[contexts][gpu][version]", gpuIdent->getDriver().toStdString());
ch.setAnnotation("gpu_memory", std::to_string(gpuIdent->getMemory()));
}
// make sure the debug draw singleton is initialized on the main thread.
@ -1166,13 +1170,15 @@ Application::Application(
_logger->setSessionID(accountManager->getSessionID());
#endif
setCrashAnnotation("metaverse_session_id", accountManager->getSessionID().toString().toStdString());
setCrashAnnotation("main_thread_id", std::to_string((size_t)QThread::currentThreadId()));
auto &ch = CrashHandler::getInstance();
ch.setAnnotation("metaverse_session_id", accountManager->getSessionID().toString().toStdString());
ch.setAnnotation("main_thread_id", std::to_string((size_t)QThread::currentThreadId()));
if (steamClient) {
qCDebug(interfaceapp) << "[VERSION] SteamVR buildID:" << steamClient->getSteamVRBuildID();
}
setCrashAnnotation("steam", property(hifi::properties::STEAM).toBool() ? "1" : "0");
ch.setAnnotation("steam", property(hifi::properties::STEAM).toBool() ? "1" : "0");
qCDebug(interfaceapp) << "[VERSION] Build sequence:" << qPrintable(applicationVersion());
qCDebug(interfaceapp) << "[VERSION] MODIFIED_ORGANIZATION:" << BuildInfo::MODIFIED_ORGANIZATION;
@ -1236,7 +1242,8 @@ Application::Application(
connect(&domainHandler, SIGNAL(domainURLChanged(QUrl)), SLOT(domainURLChanged(QUrl)));
connect(&domainHandler, SIGNAL(redirectToErrorDomainURL(QUrl)), SLOT(goToErrorDomainURL(QUrl)));
connect(&domainHandler, &DomainHandler::domainURLChanged, [](QUrl domainURL){
setCrashAnnotation("domain", domainURL.toString().toStdString());
auto &ch = CrashHandler::getInstance();
ch.setAnnotation("domain", domainURL.toString().toStdString());
});
connect(&domainHandler, SIGNAL(resetting()), SLOT(resettingDomain()));
connect(&domainHandler, SIGNAL(connectedToDomain(QUrl)), SLOT(updateWindowTitle()));
@ -1348,8 +1355,9 @@ Application::Application(
setPreferredCursor(Cursor::Manager::getIconName(Cursor::Icon::SYSTEM));
}
setCrashAnnotation("display_plugin", displayPlugin->getName().toStdString());
setCrashAnnotation("hmd", displayPlugin->isHmd() ? "1" : "0");
auto &ch = CrashHandler::getInstance();
ch.setAnnotation("display_plugin", displayPlugin->getName().toStdString());
ch.setAnnotation("hmd", displayPlugin->isHmd() ? "1" : "0");
});
}
connect(this, &Application::activeDisplayPluginChanged, this, &Application::updateSystemTabletMode);
@ -1388,7 +1396,8 @@ Application::Application(
connect(myAvatar.get(), &MyAvatar::skeletonModelURLChanged, [](){
QUrl avatarURL = qApp->getMyAvatar()->getSkeletonModelURL();
setCrashAnnotation("avatar", avatarURL.toString().toStdString());
auto &ch = CrashHandler::getInstance();
ch.setAnnotation("avatar", avatarURL.toString().toStdString());
});
// Inititalize sample before registering
@ -2698,7 +2707,8 @@ void Application::updateHeartbeat() const {
}
void Application::onAboutToQuit() {
setCrashAnnotation("shutdown", "1");
auto &ch = CrashHandler::getInstance();
ch.setAnnotation("shutdown", "1");
// quickly save AvatarEntityData before the EntityTree is dismantled
getMyAvatar()->saveAvatarEntityDataToSettings();
@ -7147,7 +7157,8 @@ void Application::updateWindowTitle() const {
QString metaverseUsername = accountManager->getAccountInfo().getUsername();
QString domainUsername = domainAccountManager->getUsername();
setCrashAnnotation("sentry[user][username]", metaverseUsername.toStdString());
auto &ch = CrashHandler::getInstance();
ch.setAnnotation("sentry[user][username]", metaverseUsername.toStdString());
QString currentPlaceName;
if (isServerlessMode()) {

View file

@ -34,6 +34,7 @@
#include <SettingManager.h>
#include <DependencyManager.h>
#include <UserActivityLogger.h>
#include <crash-handler/CrashHandler.h>
#include <BuildInfo.h>
bool CrashRecoveryHandler::checkForResetSettings(bool wasLikelyCrash, bool suppressPrompt) {
@ -91,7 +92,7 @@ bool CrashRecoveryHandler::suggestCrashReporting() {
QVBoxLayout* layout = new QVBoxLayout;
QString explainText;
auto &ual = UserActivityLogger::getInstance();
auto &ch = CrashHandler::getInstance();
@ -119,7 +120,7 @@ bool CrashRecoveryHandler::suggestCrashReporting() {
break;
}
if (!ual.isCrashMonitorStarted()) {
if (!ch.isStarted()) {
qWarning() << "Crash reporting not working, skipping suggestion to enable it.";
return false;
}
@ -131,8 +132,8 @@ bool CrashRecoveryHandler::suggestCrashReporting() {
QCheckBox* crashReportCheckbox = new QCheckBox("Enable automatic crash reporting");
crashReportCheckbox->setChecked(ual.isCrashReportingEnabled());
crashReportCheckbox->setEnabled(ual.isCrashMonitorStarted());
crashReportCheckbox->setChecked(ch.isEnabled());
crashReportCheckbox->setEnabled(ch.isStarted());
layout->addWidget(explainLabel);
layout->addSpacing(12);
@ -149,7 +150,7 @@ bool CrashRecoveryHandler::suggestCrashReporting() {
crashDialog.exec();
ual.setCrashReportingEnabled(crashReportCheckbox->isChecked());
ch.setEnabled(crashReportCheckbox->isChecked());
return true;
}
@ -157,7 +158,7 @@ bool CrashRecoveryHandler::suggestCrashReporting() {
CrashRecoveryHandler::Action CrashRecoveryHandler::promptUserForAction(bool showCrashMessage) {
QDialog crashDialog;
QLabel* label;
auto &ual = UserActivityLogger::getInstance();
auto &ch = CrashHandler::getInstance();
if (showCrashMessage) {
crashDialog.setWindowTitle("Interface Crashed Last Run");
@ -176,7 +177,7 @@ CrashRecoveryHandler::Action CrashRecoveryHandler::promptUserForAction(bool show
QRadioButton* option3 = new QRadioButton("Continue with my current settings");
QLabel* crashReportLabel = nullptr;
if (ual.isCrashMonitorStarted()) {
if (ch.isStarted()) {
crashReportLabel = new QLabel("To help us with debugging, you can enable automatic crash reports.\n"
"They'll only be seen by developers trusted by the Overte e.V. organization,\n"
"and will only be used for improving the code.");
@ -187,8 +188,8 @@ CrashRecoveryHandler::Action CrashRecoveryHandler::promptUserForAction(bool show
QCheckBox* crashReportCheckbox = new QCheckBox("Enable automatic crash reporting");
crashReportCheckbox->setChecked(ual.isCrashReportingEnabled());
crashReportCheckbox->setEnabled(ual.isCrashMonitorStarted());
crashReportCheckbox->setChecked(ch.isEnabled());
crashReportCheckbox->setEnabled(ch.isStarted());
option3->setChecked(true);
layout->addWidget(option1);
@ -218,7 +219,7 @@ CrashRecoveryHandler::Action CrashRecoveryHandler::promptUserForAction(bool show
}
}
ual.setCrashReportingEnabled(crashReportCheckbox->isChecked());
ch.setEnabled(crashReportCheckbox->isChecked());
// Dialog cancelled or "do nothing" option chosen
return CrashRecoveryHandler::DO_NOTHING;

View file

@ -22,8 +22,8 @@
#include <plugins/SteamClientPlugin.h>
#include <UserActivityLogger.h>
#include <UUID.h>
#include <crash-handler/CrashHandler.h>
#include "CrashHandler.h"
#include "Menu.h"
const Discoverability::Mode DEFAULT_DISCOVERABILITY_MODE = Discoverability::Connections;
@ -133,7 +133,8 @@ void DiscoverabilityManager::updateLocation() {
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
steamClient->updateLocation(domainHandler.getHostname(), currentAddress);
}
setCrashAnnotation("address", currentAddress.toString().toStdString());
CrashHandler::getInstance().setAnnotation("address", currentAddress.toString().toStdString());
}
void DiscoverabilityManager::handleHeartbeatResponse(QNetworkReply* requestReply) {

View file

@ -57,6 +57,7 @@
#include "LocationBookmarks.h"
#include "DeferredLightingEffect.h"
#include "PickManager.h"
#include "crash-handler/CrashHandler.h"
#include "scripting/SettingsScriptingInterface.h"
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
@ -636,12 +637,13 @@ Menu::Menu() {
true,
&UserActivityLogger::getInstance(),
SLOT(disable(bool)));
addCheckableActionToQMenuAndActionHash(networkMenu,
MenuOption::EnableCrashReporting,
0,
UserActivityLogger::getInstance().isCrashReportingEnabled(),
&UserActivityLogger::getInstance(),
SLOT(setCrashReportingEnabled(bool)));
CrashHandler::getInstance().isEnabled(),
&CrashHandler::getInstance(),
SLOT(setEnabled(bool)));
addActionToQMenuAndActionHash(networkMenu, MenuOption::ShowDSConnectTable, 0,
qApp, SLOT(loadDomainConnectionDialog()));

View file

@ -12,8 +12,8 @@
#include "Application.h"
#include <shared/GlobalAppProperties.h>
#include <shared/QtHelpers.h>
#include <crash-handler/CrashHandler.h>
#include "CrashHandler.h"
RenderEventHandler::RenderEventHandler(CheckCall checkCall, RenderCall renderCall) :
_checkCall(checkCall),
@ -29,7 +29,7 @@ RenderEventHandler::RenderEventHandler(CheckCall checkCall, RenderCall renderCal
void RenderEventHandler::initialize() {
setObjectName("Render");
PROFILE_SET_THREAD_NAME("Render");
setCrashAnnotation("render_thread_id", std::to_string((size_t)QThread::currentThreadId()));
CrashHandler::getInstance().setAnnotation("render_thread_id", std::to_string((size_t)QThread::currentThreadId()));
}
void RenderEventHandler::resumeThread() {

View file

@ -27,7 +27,7 @@
#include "AddressManager.h"
#include "Application.h"
#include "CrashHandler.h"
#include "crash-handler/CrashHandler.h"
#include "InterfaceLogging.h"
#include "UserActivityLogger.h"
#include "MainWindow.h"
@ -37,7 +37,7 @@
#ifdef Q_OS_WIN
#include <Windows.h>
extern "C" {
typedef int(__stdcall * CHECKMINSPECPROC) ();
typedef int(__stdcall* CHECKMINSPECPROC)();
}
#endif
@ -51,7 +51,7 @@ int main(int argc, const char* argv[]) {
// This appears to resolve the issues with corrupted fonts on OSX. No
// idea why.
qputenv("QT_ENABLE_GLYPH_CACHE_WORKAROUND", "true");
// https://i.kym-cdn.com/entries/icons/original/000/008/342/ihave.jpg
// https://i.kym-cdn.com/entries/icons/original/000/008/342/ihave.jpg
QSurfaceFormat::setDefaultFormat(format);
#endif
@ -73,179 +73,88 @@ int main(int argc, const char* argv[]) {
QCommandLineOption helpOption = parser.addHelpOption();
QCommandLineOption versionOption = parser.addVersionOption();
QCommandLineOption urlOption(
"url",
"Start at specified URL location.",
"string"
);
QCommandLineOption protocolVersionOption(
"protocolVersion",
"Writes the protocol version base64 signature to a file?",
"path"
);
QCommandLineOption noUpdaterOption(
"no-updater",
"Do not show auto-updater."
);
QCommandLineOption checkMinSpecOption(
"checkMinSpec",
"Check if machine meets minimum specifications. The program will run if check passes."
);
QCommandLineOption runServerOption(
"runServer",
"Run the server."
);
QCommandLineOption listenPortOption(
"listenPort",
"Port to listen on.",
"port_number"
);
QCommandLineOption serverContentPathOption(
"serverContentPath",
"Path to find server content.", // What content??
"path"
);
QCommandLineOption overrideAppLocalDataPathOption(
"cache",
"Set test cache.",
"dir"
);
QCommandLineOption scriptsOption(
"scripts",
"Set path for defaultScripts. These are probably scripts that run automatically. This parameter does not seem to work.",
"dir"
);
QCommandLineOption allowMultipleInstancesOption(
"allowMultipleInstances",
"Allow multiple instances to run."
);
QCommandLineOption displaysOption(
"display",
"Preferred display.",
"displays"
);
QCommandLineOption disableDisplaysOption(
"disable-displays",
"Displays to disable. Valid options include \"OpenVR (Vive)\" and \"Oculus Rift\"",
"string"
);
QCommandLineOption disableInputsOption(
"disable-inputs",
"Inputs to disable. Valid options include \"OpenVR (Vive)\" and \"Oculus Rift\"",
"string"
);
QCommandLineOption suppressSettingsResetOption(
"suppress-settings-reset",
"Suppress the prompt to reset interface settings."
);
QCommandLineOption oculusStoreOption(
"oculus-store",
"Let the Oculus plugin know if interface was run from the Oculus Store."
);
QCommandLineOption standaloneOption(
"standalone",
"Emulate a standalone device."
);
QCommandLineOption disableWatchdogOption(
"disableWatchdog",
"Disable the watchdog thread. The interface will crash on deadlocks."
);
QCommandLineOption systemCursorOption(
"system-cursor",
"Use the default system cursor."
);
QCommandLineOption concurrentDownloadsOption(
"concurrent-downloads",
"Maximum concurrent resource downloads. Default is 16, except for Android where it is 4.",
"integer"
);
QCommandLineOption avatarURLOption(
"avatarURL",
"Override the avatar U.R.L.",
"url"
);
QCommandLineOption replaceAvatarURLOption(
"replaceAvatarURL",
"Replaces the avatar U.R.L. When used with --avatarURL, this takes precedence.",
"url"
);
QCommandLineOption setBookmarkOption(
"setBookmark",
"Set bookmark as key=value pair. Including the '=' symbol in either string is unsupported.",
"string"
);
QCommandLineOption forceCrashReportingOption(
"forceCrashReporting",
"Force crash reporting to initialize."
);
QCommandLineOption urlOption("url", "Start at specified URL location.", "string");
QCommandLineOption protocolVersionOption("protocolVersion", "Writes the protocol version base64 signature to a file?",
"path");
QCommandLineOption noUpdaterOption("no-updater", "Do not show auto-updater.");
QCommandLineOption
checkMinSpecOption("checkMinSpec",
"Check if machine meets minimum specifications. The program will run if check passes.");
QCommandLineOption runServerOption("runServer", "Run the server.");
QCommandLineOption listenPortOption("listenPort", "Port to listen on.", "port_number");
QCommandLineOption serverContentPathOption("serverContentPath",
"Path to find server content.", // What content??
"path");
QCommandLineOption overrideAppLocalDataPathOption("cache", "Set test cache.", "dir");
QCommandLineOption scriptsOption("scripts",
"Set path for defaultScripts. These are probably scripts that run automatically. This "
"parameter does not seem to work.",
"dir");
QCommandLineOption allowMultipleInstancesOption("allowMultipleInstances", "Allow multiple instances to run.");
QCommandLineOption displaysOption("display", "Preferred display.", "displays");
QCommandLineOption disableDisplaysOption("disable-displays",
"Displays to disable. Valid options include \"OpenVR (Vive)\" and \"Oculus Rift\"",
"string");
QCommandLineOption disableInputsOption("disable-inputs",
"Inputs to disable. Valid options include \"OpenVR (Vive)\" and \"Oculus Rift\"",
"string");
QCommandLineOption suppressSettingsResetOption("suppress-settings-reset",
"Suppress the prompt to reset interface settings.");
QCommandLineOption oculusStoreOption("oculus-store",
"Let the Oculus plugin know if interface was run from the Oculus Store.");
QCommandLineOption standaloneOption("standalone", "Emulate a standalone device.");
QCommandLineOption disableWatchdogOption("disableWatchdog",
"Disable the watchdog thread. The interface will crash on deadlocks.");
QCommandLineOption systemCursorOption("system-cursor", "Use the default system cursor.");
QCommandLineOption
concurrentDownloadsOption("concurrent-downloads",
"Maximum concurrent resource downloads. Default is 16, except for Android where it is 4.",
"integer");
QCommandLineOption avatarURLOption("avatarURL", "Override the avatar U.R.L.", "url");
QCommandLineOption replaceAvatarURLOption("replaceAvatarURL",
"Replaces the avatar U.R.L. When used with --avatarURL, this takes precedence.",
"url");
QCommandLineOption
setBookmarkOption("setBookmark",
"Set bookmark as key=value pair. Including the '=' symbol in either string is unsupported.",
"string");
QCommandLineOption forceCrashReportingOption("forceCrashReporting", "Force crash reporting to initialize.");
// The documented "--disable-lod" does not seem to exist.
// Below are undocumented.
QCommandLineOption noLauncherOption(
"no-launcher",
"Supposedly does something for the server, unrelated to the application launcher. The feature may never have been implemented."
);
QCommandLineOption overrideScriptsPathOption(
"overrideScriptsPath",
"Specifies path to default directory where the application will look for scripts to load.",
"string"
);
QCommandLineOption defaultScriptsOverrideOption(
"defaultScriptsOverride",
"Override default script to run automatically on start. Default is \"defaultsScripts.js\".",
"string"
);
QCommandLineOption responseTokensOption(
"tokens",
"Set response tokens <json>.",
"json"
);
QCommandLineOption displayNameOption(
"displayName",
"Set user display name <string>.",
"string"
);
QCommandLineOption noLoginOption(
"no-login-suggestion",
"Do not show log-in dialogue."
);
QCommandLineOption traceFileOption(
"traceFile",
"Writes a trace to a file in the documents folder. Only works if \"--traceDuration\" is specified.",
"path"
);
QCommandLineOption traceDurationOption(
"traceDuration",
"Automatically quit interface after duration. Only works if \"--traceFile\" is specified.",
"seconds"
);
QCommandLineOption clockSkewOption(
"clockSkew",
"Forces client instance's clock to skew for demonstration purposes.",
"integer"
); // This should probably be removed.
QCommandLineOption testScriptOption(
"testScript",
"Undocumented. Accepts parameter as U.R.L.",
"string"
);
QCommandLineOption testResultsLocationOption(
"testResultsLocation",
"Undocumented",
"path"
);
QCommandLineOption noLauncherOption("no-launcher",
"Supposedly does something for the server, unrelated to the application launcher. The "
"feature may never have been implemented.");
QCommandLineOption
overrideScriptsPathOption("overrideScriptsPath",
"Specifies path to default directory where the application will look for scripts to load.",
"string");
QCommandLineOption defaultScriptsOverrideOption("defaultScriptsOverride",
"Override default script to run automatically on start. Default is "
"\"defaultsScripts.js\".",
"string");
QCommandLineOption responseTokensOption("tokens", "Set response tokens <json>.", "json");
QCommandLineOption displayNameOption("displayName", "Set user display name <string>.", "string");
QCommandLineOption noLoginOption("no-login-suggestion", "Do not show log-in dialogue.");
QCommandLineOption
traceFileOption("traceFile",
"Writes a trace to a file in the documents folder. Only works if \"--traceDuration\" is specified.",
"path");
QCommandLineOption
traceDurationOption("traceDuration",
"Automatically quit interface after duration. Only works if \"--traceFile\" is specified.",
"seconds");
QCommandLineOption clockSkewOption("clockSkew", "Forces client instance's clock to skew for demonstration purposes.",
"integer"); // This should probably be removed.
QCommandLineOption testScriptOption("testScript", "Undocumented. Accepts parameter as U.R.L.", "string");
QCommandLineOption testResultsLocationOption("testResultsLocation", "Undocumented", "path");
QCommandLineOption quitWhenFinishedOption(
"quitWhenFinished",
"Only works if \"--testScript\" is provided."
); // Should probably also be made to work on testResultsLocationOption.
QCommandLineOption fastHeartbeatOption(
"fast-heartbeat",
"Change stats polling interval from 10000ms to 1000ms."
);
QCommandLineOption logOption(
"logOptions",
"Logging options, comma separated: color,nocolor,process_id,thread_id,milliseconds,keep_repeats,journald,nojournald",
"options"
);
"quitWhenFinished",
"Only works if \"--testScript\" is provided."); // Should probably also be made to work on testResultsLocationOption.
QCommandLineOption fastHeartbeatOption("fast-heartbeat", "Change stats polling interval from 10000ms to 1000ms.");
QCommandLineOption logOption("logOptions",
"Logging options, comma separated: "
"color,nocolor,process_id,thread_id,milliseconds,keep_repeats,journald,nojournald",
"options");
// "--qmljsdebugger", which appears in output from "--help-all".
// Those below don't seem to be optional.
// --ignore-gpu-blacklist
@ -296,7 +205,7 @@ int main(int argc, const char* argv[]) {
{
QCoreApplication tempApp(argc, const_cast<char**>(argv));
parser.process(QCoreApplication::arguments()); // Must be run after QCoreApplication is initalised.
parser.process(QCoreApplication::arguments()); // Must be run after QCoreApplication is initalised.
#ifdef Q_OS_OSX
if (QFileInfo::exists(QCoreApplication::applicationDirPath() + "/../../../config.json")) {
@ -310,10 +219,10 @@ int main(int argc, const char* argv[]) {
}
// We want to configure the logging system as early as possible
auto &logHandler = LogHandler::getInstance();
auto& logHandler = LogHandler::getInstance();
if (parser.isSet(logOption)) {
if (!logHandler.parseOptions(parser.value(logOption).toUtf8(), logOption.names().first())) {
QCoreApplication mockApp(argc, const_cast<char**>(argv)); // required for call to showHelp()
QCoreApplication mockApp(argc, const_cast<char**>(argv)); // required for call to showHelp()
parser.showHelp();
Q_UNREACHABLE();
}
@ -325,7 +234,7 @@ int main(int argc, const char* argv[]) {
Q_UNREACHABLE();
}
if (parser.isSet(helpOption)) {
QCoreApplication mockApp(argc, const_cast<char**>(argv)); // required for call to showHelp()
QCoreApplication mockApp(argc, const_cast<char**>(argv)); // required for call to showHelp()
parser.showHelp();
Q_UNREACHABLE();
}
@ -378,7 +287,7 @@ int main(int argc, const char* argv[]) {
// Early check for --traceFile argument
auto tracer = DependencyManager::set<tracing::Tracer>();
const char * traceFile = nullptr;
const char* traceFile = nullptr;
float traceDuration = 0.0f;
if (parser.isSet(traceFileOption)) {
traceFile = parser.value(traceFileOption).toStdString().c_str();
@ -412,6 +321,8 @@ int main(int argc, const char* argv[]) {
// Instance UserActivityLogger now that the settings are loaded
auto& ual = UserActivityLogger::getInstance();
auto& ch = CrashHandler::getInstance();
// once the settings have been loaded, check if we need to flip the default for UserActivityLogger
if (!ual.isDisabledSettingSet()) {
// the user activity logger is opt-out for Interface
@ -423,13 +334,12 @@ int main(int argc, const char* argv[]) {
if (parser.isSet(forceCrashReportingOption)) {
qInfo() << "Crash reporting enabled on the command-line";
ual.setCrashReportingEnabled(true);
ch.setEnabled(true);
}
auto crashHandlerStarted = startCrashHandler(argv[0]);
auto crashHandlerStarted = ch.start(argv[0]);
if (crashHandlerStarted) {
ual.setCrashMonitorStarted(true);
qDebug() << "Crash handler started:" << crashHandlerStarted;
qDebug() << "Crash handler started";
} else {
qWarning() << "Crash handler failed to start";
}
@ -472,9 +382,9 @@ int main(int argc, const char* argv[]) {
if (socket.waitForConnected(LOCAL_SERVER_TIMEOUT_MS)) {
if (parser.isSet(urlOption)) {
QUrl url = QUrl(parser.value(urlOption));
if (url.isValid() && (url.scheme() == URL_SCHEME_OVERTE || url.scheme() == URL_SCHEME_OVERTEAPP
|| url.scheme() == HIFI_URL_SCHEME_HTTP || url.scheme() == HIFI_URL_SCHEME_HTTPS
|| url.scheme() == HIFI_URL_SCHEME_FILE)) {
if (url.isValid() && (url.scheme() == URL_SCHEME_OVERTE || url.scheme() == URL_SCHEME_OVERTEAPP ||
url.scheme() == HIFI_URL_SCHEME_HTTP || url.scheme() == HIFI_URL_SCHEME_HTTPS ||
url.scheme() == HIFI_URL_SCHEME_FILE)) {
qDebug() << "Writing URL to local socket";
socket.write(url.toString().toUtf8());
if (!socket.waitForBytesWritten(5000)) {
@ -495,7 +405,6 @@ int main(int argc, const char* argv[]) {
#endif
}
// FIXME this method of checking the OpenGL version screws up the `QOpenGLContext::globalShareContext()` value, which in turn
// leads to crashes when creating the real OpenGL instance. Disabling for now until we come up with a better way of checking
// the GL version on the system without resorting to creating a full Qt application
@ -522,7 +431,6 @@ int main(int argc, const char* argv[]) {
}
#endif
// Debug option to demonstrate that the client's local time does not
// need to be in sync with any other network node. This forces clock
// skew for the individual client
@ -590,7 +498,8 @@ int main(int argc, const char* argv[]) {
#if defined(Q_OS_LINUX)
app.setWindowIcon(QIcon(PathUtils::resourcesPath() + "images/brand-logo.svg"));
#endif
startCrashHookMonitor(&app);
ch.startMonitor(&app);
QTimer exitTimer;
if (traceDuration > 0.0f) {
@ -618,14 +527,14 @@ int main(int argc, const char* argv[]) {
#endif
// Setup local server
QLocalServer server { &app };
QLocalServer server{ &app };
// We failed to connect to a local server, so we remove any existing servers.
server.removeServer(applicationName);
server.listen(applicationName);
QObject::connect(&server, &QLocalServer::newConnection,
&app, &Application::handleLocalServerConnection, Qt::DirectConnection);
QObject::connect(&server, &QLocalServer::newConnection, &app, &Application::handleLocalServerConnection,
Qt::DirectConnection);
printSystemInformation();

View file

@ -5,13 +5,6 @@ link_hifi_libraries(shared networking)
add_crashpad()
target_breakpad()
if (UNIX AND NOT APPLE)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(Threads::Threads)
endif()
if (WIN32)
add_compile_definitions(_USE_MATH_DEFINES)
endif()

View file

@ -0,0 +1,61 @@
//
// CrashHandler.cpp
//
//
// Created by Dale Glass on 25/06/2023.
// Copyright 2023 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "CrashHandler.h"
#include "CrashHandlerBackend.h"
CrashHandler& CrashHandler::getInstance() {
static CrashHandler sharedInstance;
return sharedInstance;
}
bool CrashHandler::start(const QString &path) {
if (isStarted()) {
qCWarning(crash_handler) << "Crash handler already started";
return false;
}
auto started = startCrashHandler(path.toStdString());
setStarted(started);
if ( started ) {
qCInfo(crash_handler) << "Crash handler started";
} else {
qCWarning(crash_handler) << "Crash handler failed to start";
}
return started;
}
void CrashHandler::startMonitor(QCoreApplication *app) {
startCrashHookMonitor(app);
}
void CrashHandler::setEnabled(bool enabled) {
if (enabled != _crashReportingEnabled.get()) {
_crashReportingEnabled.set(enabled);
setCrashReportingEnabled(enabled);
}
}
void CrashHandler::setAnnotation(const std::string &key, const char *value) {
setCrashAnnotation(key, std::string(value));
}
void CrashHandler::setAnnotation(const std::string &key, const QString &value) {
setCrashAnnotation(key, value.toStdString());
}
void CrashHandler::setAnnotation(const std::string &key, const std::string &value) {
setCrashAnnotation(key, value);
}

View file

@ -1,27 +1,107 @@
//
// CrashHandler.h
// interface/src
// CrashHandler.cpp
//
// Created by Clement Brisset on 01/19/18.
// Copyright 2018 High Fidelity, Inc.
//
// Created by Dale Glass on 25/06/2023.
// Copyright 2023 Overte e.V.
//
// 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_CrashHandler_h
#define hifi_CrashHandler_h
#pragma once
#include <string>
#include <QObject>
#include <QCoreApplication>
#include <QLoggingCategory>
Q_DECLARE_LOGGING_CATEGORY(crash_handler)
bool startCrashHandler(std::string appPath);
void setCrashAnnotation(std::string name, std::string value);
void startCrashHookMonitor(QCoreApplication* app);
void setCrashReportingEnabled(bool value);
#include <SettingHandle.h>
/**
* @brief The global object in charge of setting up and controlling crash reporting.
*
* This object initializes and talks to crash reporting backends.
*
*/
class CrashHandler : public QObject {
Q_OBJECT
public:
static CrashHandler& getInstance();
public slots:
/**
* @brief Start the crash handler
*
* @param path Database path
* @return true Started successfully
* @return false Failed to start
*/
bool start(const QString &path);
void startMonitor(QCoreApplication *app);
/**
* @brief Whether the crash monitor has been successfully started
*
* Reasons for it failing to start include:
*
* * Not having a crash reporter for the platform
* * Crash reporter not being configured with reporting URLs (CMAKE_BACKTRACE_TOKEN and CMAKE_BACKTRACE_URL)
* * Crash reporter is present and configured, but failed to initialize for some reason
*
* @return true Crash reporter is present, configured and working.
* @return false Crash reporter has not been started for one of the above reasons.
*/
bool isStarted() const { return _crashMonitorStarted; }
/**
* @brief Whether the crash monitor will report crashes if they occur
*
* This setting is independent of isCrashMonitorStarted() -- crash reporting may be enabled but fail to work
* due to the crash reporting component being missing or failing to initialize.
*
* @return true Crashes will be reported to CMAKE_BACKTRACE_URL
* @return false Crashes will not be reported
*/
bool isEnabled() const { return _crashReportingEnabled.get(); }
/**
* @brief Set whether we want to submit crash reports to the report server
*
* The report server is configured with CMAKE_BACKTRACE_URL.
* Emits crashReportingEnabledChanged signal.
*
* @param enabled Whether it's enabled.
*/
void setEnabled(bool enabled);
void setAnnotation(const std::string &key, const char *value);
void setAnnotation(const std::string &key, const QString &value);
void setAnnotation(const std::string &key, const std::string &value);
private:
/**
* @brief Marks the crash monitor as started
*
* @warning Only to be used as part of the startup process
*
* @param started
*/
void setStarted(bool started) { _crashMonitorStarted = started; }
Setting::Handle<bool> _crashReportingEnabled { "CrashReportingEnabled", false };
bool _crashMonitorStarted {false};
};
#endif // hifi_CrashHandler_h

View file

@ -0,0 +1,27 @@
//
// CrashHandler.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_CrashHandlerBackend_h
#define hifi_CrashHandlerBackend_h
#include <string>
#include <QCoreApplication>
#include <QLoggingCategory>
Q_DECLARE_LOGGING_CATEGORY(crash_handler)
bool startCrashHandler(std::string appPath);
void setCrashAnnotation(std::string name, std::string value);
void startCrashHookMonitor(QCoreApplication* app);
void setCrashReportingEnabled(bool value);
#endif // hifi_CrashHandlerBackend_h

View file

@ -421,12 +421,12 @@ bool startCrashHandler(std::string appPath) {
}
// Enable automated uploads.
QObject::connect(&UserActivityLogger::getInstance(), &UserActivityLogger::crashReportingEnabledChanged, []() {
auto &ual = UserActivityLogger::getInstance();
setCrashReportingEnabled(ual.isCrashReportingEnabled());
});
// QObject::connect(&UserActivityLogger::getInstance(), &UserActivityLogger::crashReportingEnabledChanged, []() {
// auto &ual = UserActivityLogger::getInstance();
// setCrashReportingEnabled(ual.isCrashReportingEnabled());
// });
crashpadDatabase->GetSettings()->SetUploadsEnabled(UserActivityLogger::getInstance().isCrashReportingEnabled());
crashpadDatabase->GetSettings()->SetUploadsEnabled(CrashHandler::getInstance().isEnabled());
if (!client->StartHandler(handler, db, db, BACKTRACE_URL, annotations, arguments, true, true)) {

View file

@ -82,15 +82,6 @@ void UserActivityLogger::requestError(QNetworkReply* errorReply) {
qCDebug(networking) << errorReply->error() << "-" << errorReply->errorString();
}
void UserActivityLogger::setCrashReportingEnabled(bool enabled) {
bool old = _crashReportingEnabled.get();
_crashReportingEnabled.set(enabled);
if (old != enabled) {
emit crashReportingEnabledChanged();
}
}
void UserActivityLogger::launch(QString applicationVersion, bool previousSessionCrashed, int previousSessionRuntime) {
const QString ACTION_NAME = "launch";
QJsonObject actionDetails;

View file

@ -36,51 +36,6 @@ public slots:
bool isDisabledSettingSet() const { return _disabled.isSet(); }
/**
* @brief Whether the crash monitor has been successfully started
*
* Reasons for it failing to start include:
*
* * Not having a crash reporter for the platform
* * Crash reporter not being configured with reporting URLs (CMAKE_BACKTRACE_TOKEN and CMAKE_BACKTRACE_URL)
* * Crash reporter is present and configured, but failed to initialize for some reason
*
* @return true Crash reporter is present, configured and working.
* @return false Crash reporter has not been started for one of the above reasons.
*/
bool isCrashMonitorStarted() const { return _crashMonitorStarted; }
/**
* @brief Whether the crash monitor will report crashes if they occur
*
* This setting is independent of isCrashMonitorStarted() -- crash reporting may be enabled but fail to work
* due to the crash reporting component being missing or failing to initialize.
*
* @return true Crashes will be reported to CMAKE_BACKTRACE_URL
* @return false Crashes will not be reported
*/
bool isCrashReportingEnabled() { return _crashReportingEnabled.get(); }
/**
* @brief Marks the crash monitor as started
*
* @warning Only to be used as part of the startup process
*
* @param started
*/
void setCrashMonitorStarted(bool started) { _crashMonitorStarted = started; }
/**
* @brief Set whether we want to submit crash reports to the report server
*
* The report server is configured with CMAKE_BACKTRACE_URL.
* Emits crashReportingEnabledChanged signal.
*
* @param enabled Whether it's enabled.
*/
void setCrashReportingEnabled(bool enabled);
void disable(bool disable);
void logAction(QString action, QJsonObject details = QJsonObject(), JSONCallbackParameters params = JSONCallbackParameters());
@ -111,9 +66,9 @@ private slots:
private:
UserActivityLogger();
Setting::Handle<bool> _disabled { "UserActivityLoggerDisabled", true };
Setting::Handle<bool> _crashReportingEnabled { "CrashReportingEnabled", false };
bool _crashMonitorStarted {false};
QElapsedTimer _timer;
};