diff --git a/interface/src/Crashpad.cpp b/interface/src/Crashpad.cpp index 8ed3fc23bd..27da619af1 100644 --- a/interface/src/Crashpad.cpp +++ b/interface/src/Crashpad.cpp @@ -31,10 +31,41 @@ using namespace crashpad; static const std::string BACKTRACE_URL { CMAKE_BACKTRACE_URL }; static const std::string BACKTRACE_TOKEN { CMAKE_BACKTRACE_TOKEN }; +static std::wstring gIPCPipe; + extern QString qAppFileName(); // crashpad::AnnotationList* crashpadAnnotations { nullptr }; +#include + +LONG WINAPI vectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) { + static const DWORD EXTERNAL_EXCEPTION_CODE{ 0xe06d7363 }; + static const DWORD HEAP_CORRUPTION_CODE{ 0xc0000374 }; + + auto exceptionCode = pExceptionInfo->ExceptionRecord->ExceptionCode; + if (exceptionCode == EXTERNAL_EXCEPTION_CODE) { + return EXCEPTION_CONTINUE_SEARCH; + } + + if (exceptionCode == HEAP_CORRUPTION_CODE) { + qCritical() << "VectoredExceptionHandler: Heap corruption:" << QString::number(exceptionCode, 16); + + CrashpadClient client; + if (gIPCPipe.length()) { + bool rc = client.SetHandlerIPCPipe(gIPCPipe); + qCritical() << "SetHandlerIPCPipe = " << rc; + } else { + qCritical() << "No IPC Pipe was previously defined for crash handler."; + } + qCritical() << "Calling DumpAndCrash()"; + client.DumpAndCrash(pExceptionInfo); + return EXCEPTION_CONTINUE_SEARCH; + } + + return EXCEPTION_CONTINUE_SEARCH; +} + bool startCrashHandler() { if (BACKTRACE_URL.empty() || BACKTRACE_TOKEN.empty()) { return false; @@ -76,7 +107,12 @@ bool startCrashHandler() { // Enable automated uploads. database->GetSettings()->SetUploadsEnabled(true); - return client.StartHandler(handler, db, db, BACKTRACE_URL, annotations, arguments, true, true); + bool result = client.StartHandler(handler, db, db, BACKTRACE_URL, annotations, arguments, true, true); + gIPCPipe = client.GetHandlerIPCPipe(); + + AddVectoredExceptionHandler(0, vectoredExceptionHandler); + + return result; } void setCrashAnnotation(std::string name, std::string value) { diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 83199f5ba7..4384635147 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -750,32 +750,32 @@ Menu::Menu() { action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashPureVirtualFunction); connect(action, &QAction::triggered, qApp, []() { crash::pureVirtualCall(); }); action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashPureVirtualFunctionThreaded); - connect(action, &QAction::triggered, qApp, []() { std::thread([]() { crash::pureVirtualCall(); }); }); + connect(action, &QAction::triggered, qApp, []() { std::thread(crash::pureVirtualCall).join(); }); action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashDoubleFree); connect(action, &QAction::triggered, qApp, []() { crash::doubleFree(); }); action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashDoubleFreeThreaded); - connect(action, &QAction::triggered, qApp, []() { std::thread([]() { crash::doubleFree(); }); }); + connect(action, &QAction::triggered, qApp, []() { std::thread(crash::doubleFree).join(); }); action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashAbort); connect(action, &QAction::triggered, qApp, []() { crash::doAbort(); }); action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashAbortThreaded); - connect(action, &QAction::triggered, qApp, []() { std::thread([]() { crash::doAbort(); }); }); + connect(action, &QAction::triggered, qApp, []() { std::thread(crash::doAbort).join(); }); action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashNullDereference); connect(action, &QAction::triggered, qApp, []() { crash::nullDeref(); }); action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashNullDereferenceThreaded); - connect(action, &QAction::triggered, qApp, []() { std::thread([]() { crash::nullDeref(); }); }); + connect(action, &QAction::triggered, qApp, []() { std::thread(crash::nullDeref).join(); }); action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashOutOfBoundsVectorAccess); connect(action, &QAction::triggered, qApp, []() { crash::outOfBoundsVectorCrash(); }); action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashOutOfBoundsVectorAccessThreaded); - connect(action, &QAction::triggered, qApp, []() { std::thread([]() { crash::outOfBoundsVectorCrash(); }); }); + connect(action, &QAction::triggered, qApp, []() { std::thread(crash::outOfBoundsVectorCrash).join(); }); action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashNewFault); connect(action, &QAction::triggered, qApp, []() { crash::newFault(); }); action = addActionToQMenuAndActionHash(crashMenu, MenuOption::CrashNewFaultThreaded); - connect(action, &QAction::triggered, qApp, []() { std::thread([]() { crash::newFault(); }); }); + connect(action, &QAction::triggered, qApp, []() { std::thread(crash::newFault).join(); }); // Developer > Log... addActionToQMenuAndActionHash(developerMenu, MenuOption::Log, Qt::CTRL | Qt::SHIFT | Qt::Key_L,