diff --git a/interface/src/CrashReporter.cpp b/interface/src/CrashReporter.cpp index 1fd534ffac..596c34ca92 100644 --- a/interface/src/CrashReporter.cpp +++ b/interface/src/CrashReporter.cpp @@ -10,16 +10,20 @@ // -#ifdef HAS_BUGSPLAT +#include "Application.h" #include "CrashReporter.h" +#ifdef _WIN32 #include #include +#include #include - #include + +#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 @@ -77,13 +81,37 @@ BOOL redirectLibraryFunctionToFunction(char* library, char* function, void* fn) 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 handlePureVirtualCall() { +void __cdecl handlePureVirtualCall() { + qWarning() << "Pure virtual function call detected"; + printStackTrace(2); // Throw so BugSplat can handle throw("ERROR: Pure virtual call"); } @@ -107,6 +135,8 @@ _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) @@ -133,3 +163,4 @@ CrashReporter::CrashReporter(QString bugSplatDatabase, QString bugSplatApplicati } } #endif +#endif diff --git a/interface/src/FileLogger.cpp b/interface/src/FileLogger.cpp index f5f7ce6ebe..50f7d15d6b 100644 --- a/interface/src/FileLogger.cpp +++ b/interface/src/FileLogger.cpp @@ -115,3 +115,7 @@ QString FileLogger::getLogData() { } return result; } + +void FileLogger::sync() { + _persistThreadInstance->waitIdle(); +} diff --git a/interface/src/FileLogger.h b/interface/src/FileLogger.h index e9bae63a73..28ac6fba40 100644 --- a/interface/src/FileLogger.h +++ b/interface/src/FileLogger.h @@ -28,6 +28,7 @@ public: virtual void addMessage(const QString&) override; virtual QString getLogData() override; virtual void locateLog() override; + void sync(); signals: void rollingLogFile(QString newFilename); diff --git a/libraries/shared/src/GenericQueueThread.h b/libraries/shared/src/GenericQueueThread.h index 28fcdb0ed6..7c1bdccaa7 100644 --- a/libraries/shared/src/GenericQueueThread.h +++ b/libraries/shared/src/GenericQueueThread.h @@ -12,9 +12,10 @@ #include -#include -#include -#include +#include +#include +#include +#include #include "GenericThread.h" #include "NumericalConstants.h" @@ -35,6 +36,25 @@ public: _hasItems.wakeAll(); } + void waitIdle(uint32_t maxWaitMs = UINT32_MAX) { + QElapsedTimer timer; + timer.start(); + + // FIXME this will work as long as the thread doing the wait + // is the only thread which can add work to the queue. + // It would be better if instead we had a queue empty condition to wait on + // that would ensure that we get woken as soon as we're idle the very + // first time the queue was empty. + while (timer.elapsed() < maxWaitMs) { + lock(); + if (!_items.size()) { + unlock(); + return; + } + unlock(); + } + } + protected: virtual void queueItemInternal(const T& t) { _items.push_back(t); @@ -44,6 +64,7 @@ protected: return MSECS_PER_SECOND; } + virtual bool process() { lock(); if (!_items.size()) {