implemented simple crash handler

This commit is contained in:
itsmattkc
2020-02-28 13:21:32 +11:00
parent d1681bc294
commit c32ed5955c
8 changed files with 251 additions and 1 deletions
+39 -1
View File
@@ -108,7 +108,8 @@ target_include_directories(
${OIIO_INCLUDE_DIRS}
)
target_link_libraries(${OLIVE_TARGET}
target_link_libraries(
${OLIVE_TARGET}
PRIVATE
Qt5::Core
Qt5::Gui
@@ -127,6 +128,14 @@ target_link_libraries(${OLIVE_TARGET}
${OIIO_LIBRARIES}
)
if (WIN32)
target_link_libraries(
${OLIVE_TARGET}
PRIVATE
DbgHelp
)
endif()
set(OLIVE_TS_FILES
# FIXME: Empty variable
)
@@ -151,3 +160,32 @@ if(DOXYGEN_FOUND)
set(DOXYGEN_EXTRACT_PRIVATE "YES")
doxygen_add_docs(docs ALL ${OLIVE_SOURCES})
endif()
set(OLIVE_CRASH_TARGET "crashhandler")
set(OLIVE_CRASH_SOURCES
dialog/crashhandler/crashhandler.h
dialog/crashhandler/crashhandler.cpp
dialog/crashhandler/crashhandlermain.cpp
)
if (WIN32)
add_executable(
${OLIVE_CRASH_TARGET}
WIN32
${OLIVE_CRASH_SOURCES}
)
else()
add_executable(
${OLIVE_CRASH_TARGET}
${OLIVE_CRASH_SOURCES}
)
endif()
target_link_libraries(
${OLIVE_CRASH_TARGET}
PRIVATE
Qt5::Core
Qt5::Gui
Qt5::Widgets
)
+2
View File
@@ -22,6 +22,8 @@ set(OLIVE_SOURCES
common/channellayout.h
common/clamp.h
common/constructors.h
common/crashhandler.h
common/crashhandler.cpp
common/debug.h
common/debug.cpp
common/define.h
+117
View File
@@ -0,0 +1,117 @@
#include "crashhandler.h"
#include <QDir>
#include <QFile>
#include <QProcess>
#include <QStandardPaths>
#include <QTextStream>
#include <QtGlobal>
#ifdef Q_OS_WINDOWS
#include <Windows.h>
#include <DbgHelp.h>
#include <stdio.h>
#include <stdlib.h>
#endif
void crash_handler(int sig) {
QString log_path = QDir(QStandardPaths::writableLocation(QStandardPaths::TempLocation)).filePath("olive_crash");
QFile output(log_path);
output.open(QFile::WriteOnly);
QTextStream ostream(&output);
ostream << "Signal: " << sig << "\n\n";
#if defined(Q_OS_WINDOWS)
// Use Windows stackwalk API
HANDLE process = GetCurrentProcess();
HANDLE thread = GetCurrentThread();
CONTEXT context;
memset(&context, 0, sizeof(CONTEXT));
context.ContextFlags = CONTEXT_FULL;
RtlCaptureContext(&context);
SymInitialize(process, NULL, TRUE);
DWORD image;
STACKFRAME64 stackframe;
ZeroMemory(&stackframe, sizeof(STACKFRAME64));
#ifdef _M_IX86
image = IMAGE_FILE_MACHINE_I386;
stackframe.AddrPC.Offset = context.Eip;
stackframe.AddrPC.Mode = AddrModeFlat;
stackframe.AddrFrame.Offset = context.Ebp;
stackframe.AddrFrame.Mode = AddrModeFlat;
stackframe.AddrStack.Offset = context.Esp;
stackframe.AddrStack.Mode = AddrModeFlat;
#elif _M_X64
image = IMAGE_FILE_MACHINE_AMD64;
stackframe.AddrPC.Offset = context.Rip;
stackframe.AddrPC.Mode = AddrModeFlat;
stackframe.AddrFrame.Offset = context.Rsp;
stackframe.AddrFrame.Mode = AddrModeFlat;
stackframe.AddrStack.Offset = context.Rsp;
stackframe.AddrStack.Mode = AddrModeFlat;
#elif _M_IA64
image = IMAGE_FILE_MACHINE_IA64;
stackframe.AddrPC.Offset = context.StIIP;
stackframe.AddrPC.Mode = AddrModeFlat;
stackframe.AddrFrame.Offset = context.IntSp;
stackframe.AddrFrame.Mode = AddrModeFlat;
stackframe.AddrBStore.Offset = context.RsBSP;
stackframe.AddrBStore.Mode = AddrModeFlat;
stackframe.AddrStack.Offset = context.IntSp;
stackframe.AddrStack.Mode = AddrModeFlat;
#endif
for (int i = 0; i < 50; i++) {
BOOL result = StackWalk64(
image, process, thread,
&stackframe, &context, NULL,
SymFunctionTableAccess64, SymGetModuleBase64, NULL);
if (!result) { break; }
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
symbol->MaxNameLen = MAX_SYM_NAME;
DWORD64 displacement = 0;
ostream << "[" << i << "] ";
if (SymFromAddr(process, stackframe.AddrPC.Offset, &displacement, symbol)) {
ostream << symbol->Name;
//printf("[%i] %s\n", i, symbol->Name);
} else {
ostream << "???";
//printf("[%i] ???\n", i);
}
ostream << "\n";
}
SymCleanup(process);
#elif defined(Q_OS_LINUX)
void *array[10];
size_t size;
// get void*'s for all entries on the stack
size = backtrace(array, 10);
// print out all the frames to stderr
fprintf(stderr, "Error: signal %d:\n", sig);
backtrace_symbols_fd(array, size, STDERR_FILENO);
#endif
output.close();
QProcess::startDetached(QStringLiteral("crashhandler"), {log_path});
exit(1);
}
+6
View File
@@ -0,0 +1,6 @@
#ifndef CRASHHANDLER_H
#define CRASHHANDLER_H
void crash_handler(int sig);
#endif // CRASHHANDLER_H
+47
View File
@@ -0,0 +1,47 @@
#include "crashhandler.h"
#include <QFile>
#include <QLabel>
#include <QDialogButtonBox>
#include <QTextEdit>
#include <QVBoxLayout>
CrashHandlerDialog::CrashHandlerDialog(const char *log_file)
{
setWindowTitle(tr("Olive"));
QVBoxLayout* layout = new QVBoxLayout(this);
layout->addWidget(new QLabel(tr("We're sorry, Olive has crashed. Please send the following log to the developers to "
"help resolve this.")));
QTextEdit* edit = new QTextEdit();
layout->addWidget(edit);
QDialogButtonBox* buttons = new QDialogButtonBox();
// FIXME: Implement auto-reporting
//buttons->addButton(tr("Send Error Report"), QDialogButtonBox::AcceptRole);
//buttons->addButton(tr("Don't Send"), QDialogButtonBox::RejectRole);
buttons->addButton(QDialogButtonBox::Ok);
connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
layout->addWidget(buttons);
QFile log(log_file);
if (log.open(QFile::ReadOnly | QFile::Text)) {
edit->setText(log.readAll());
log.close();
}
}
void CrashHandlerDialog::accept()
{
QDialog::accept();
}
void CrashHandlerDialog::reject()
{
QDialog::reject();
}
+19
View File
@@ -0,0 +1,19 @@
#ifndef CRASHHANDLERDIALOG_H
#define CRASHHANDLERDIALOG_H
#include <QDialog>
class CrashHandlerDialog : public QDialog
{
Q_OBJECT
public:
CrashHandlerDialog(const char* log_file);
public slots:
virtual void accept() override;
virtual void reject() override;
};
#endif // CRASHHANDLERDIALOG_H
@@ -0,0 +1,17 @@
#include "crashhandler.h"
#include <QApplication>
int main(int argc, char *argv[])
{
if (argc < 2) {
return 1;
}
QApplication a(argc, argv);
CrashHandlerDialog chd(argv[1]);
chd.open();
return a.exec();
}
+4
View File
@@ -35,11 +35,15 @@ extern "C" {
#include <QSurfaceFormat>
#include "core.h"
#include "common/crashhandler.h"
#include "common/debug.h"
int main(int argc, char *argv[]) {
av_log_set_level(AV_LOG_QUIET);
signal(SIGSEGV, crash_handler);
signal(SIGABRT, crash_handler);
// Set OpenGL display profile (3.2 Core)
QSurfaceFormat format;
format.setVersion(3, 2);