crashpad: updated crash handler

This commit is contained in:
itsmattkc
2020-09-22 18:42:51 +10:00
parent 871bc08c12
commit cd47676043
11 changed files with 298 additions and 285 deletions
+3
View File
@@ -139,10 +139,13 @@ jobs:
then
mkdir olive-editor
cp app/olive-editor.exe olive-editor
cp app/olive-crashhandler.exe olive-editor
cp app/olive-editor.pdb olive-editor
windeployqt olive-editor/olive-crashhandler.exe
windeployqt olive-editor/olive-editor.exe
cp $(cygpath $GITHUB_WORKSPACE)/bin/*.dll olive-editor
cp $(cygpath $GITHUB_WORKSPACE)/out/Default/crashpad_handler.exe olive-editor
cp $(cygpath $GITHUB_WORKSPACE)/minidump_stackwalk/* olive-editor
elif [ "$MATRIX_OS" == "macos-latest" ]
then
export BUNDLE_NAME=Olive.app
+48 -40
View File
@@ -183,6 +183,54 @@ if (GoogleCrashpad_FOUND)
PRIVATE
${CRASHPAD_LIBRARIES}
)
set(OLIVE_CRASH_TARGET "olive-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_include_directories(
${OLIVE_CRASH_TARGET}
PRIVATE
${CRASHPAD_INCLUDE_DIRS}
)
target_link_libraries(
${OLIVE_CRASH_TARGET}
PRIVATE
Qt5::Core
Qt5::Gui
Qt5::Widgets
Qt5::Network
${CRASHPAD_LIBRARIES}
)
if(UNIX AND NOT APPLE)
install(TARGETS ${OLIVE_TARGET} ${OLIVE_CRASH_TARGET} RUNTIME DESTINATION bin)
endif()
if(APPLE)
# Move crash handler program inside Mac app bundle
add_custom_command(TARGET ${OLIVE_CRASH_TARGET} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${OLIVE_CRASH_TARGET} $<TARGET_FILE_DIR:${OLIVE_TARGET}>
)
endif()
endif()
# Set compiler definitions
@@ -207,43 +255,3 @@ if(DOXYGEN_FOUND)
set(DOXYGEN_EXTRACT_PRIVATE "YES")
doxygen_add_docs(docs ALL ${OLIVE_SOURCES})
endif()
set(OLIVE_CRASH_TARGET "olive-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
)
if(UNIX AND NOT APPLE)
install(TARGETS ${OLIVE_TARGET} ${OLIVE_CRASH_TARGET} RUNTIME DESTINATION bin)
endif()
if(APPLE)
# Move crash handler program inside Mac app bundle
add_custom_command(TARGET ${OLIVE_CRASH_TARGET} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${OLIVE_CRASH_TARGET} $<TARGET_FILE_DIR:${OLIVE_TARGET}>
)
endif()
+2 -3
View File
@@ -23,10 +23,9 @@ set(OLIVE_SOURCES
common/clamp.h
common/commandlineparser.h
common/commandlineparser.cpp
common/crashhandler.h
common/crashhandler.cpp
common/crashpadinterface.cpp
common/crashpadinterface.h
common/crashpadinterface.cpp
common/crashpadutils.h
common/debug.h
common/debug.cpp
common/define.h
-150
View File
@@ -1,150 +0,0 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include "crashhandler.h"
#include <QApplication>
#include <QDir>
#include <QFile>
#include <QProcess>
#include <QStandardPaths>
#include <QTextStream>
#include <QtGlobal>
#if defined(Q_OS_WINDOWS)
#include <Windows.h>
#include <DbgHelp.h>
#include <stdio.h>
#include <stdlib.h>
#elif defined(Q_OS_MAC) || defined(Q_OS_LINUX)
#include <execinfo.h>
#endif
#include "common/filefunctions.h"
OLIVE_NAMESPACE_ENTER
void crash_handler(int sig)
{
QString log_path = QDir(FileFunctions::GetTempFilePath()).filePath(QStringLiteral("olive_crash"));
QFile output(log_path);
output.open(QFile::WriteOnly);
QTextStream ostream(&output);
#ifdef GITHASH
ostream << "Version: " << GITHASH << "\n";
#endif
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_MAC) || 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
backtrace_symbols_fd(array, size, output.handle());
#endif
output.close();
QString crash_handler_exe = QDir(qApp->applicationDirPath()).filePath(QStringLiteral("olive-crashhandler"));
QProcess::startDetached(crash_handler_exe, {log_path});
exit(1);
}
OLIVE_NAMESPACE_EXIT
+38 -43
View File
@@ -23,75 +23,67 @@
#ifdef USE_CRASHPAD
#include <QCoreApplication>
#include <QDateTime>
#include <QDebug>
#include <QDir>
#include <QMessageBox>
#include <QProcess>
#include "crashpadutils.h"
#include "filefunctions.h"
#ifdef Q_OS_WINDOWS
#ifdef OS_WIN
#include <Windows.h>
#endif
// Copied from base::FilePath to match its macro
#if defined(OS_POSIX)
// On most platforms, native pathnames are char arrays, and the encoding
// may or may not be specified. On Mac OS X, native pathnames are encoded
// in UTF-8.
#define TO_BASE_STRING_TYPE(x) x.toStdString()
#elif defined(OS_WIN)
// On Windows, for Unicode-aware applications, native pathnames are wchar_t
// arrays encoded in UTF-16.
#define TO_BASE_STRING_TYPE(x) x.toStdWString()
#endif // OS_WIN
crashpad::CrashpadClient *client;
bool ShowCrashConfirmation()
QString GenerateReportPath()
{
QString msg = QCoreApplication::translate("CrashReport",
"We're sorry, Olive has crashed. "
"Would you like to send an error report to "
"help developers fix this issue?\n\n"
"Crash reports are anonymous and only send "
"non-specific details about your computer and"
"how the crash occurred.");
return (QMessageBox::critical(nullptr,
QString(),
msg,
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes);
return QDir(OLIVE_NAMESPACE::FileFunctions::GetTempFilePath()).filePath(QStringLiteral("reports"));
}
#ifdef Q_OS_WINDOWS
base::FilePath GenerateReportPathForCrashpad()
{
return base::FilePath(QSTRING_TO_BASE_STRING(GenerateReportPath()));
}
#if defined(OS_WIN)
LONG WINAPI Win32ExceptionHandler(_EXCEPTION_POINTERS *ExceptionInfo)
{
if (ShowCrashConfirmation()) {
client->DumpAndCrash(ExceptionInfo);
}
QString crash_handler_exe = QDir(qApp->applicationDirPath()).filePath(QStringLiteral("olive-crashhandler"));
QProcess::startDetached(crash_handler_exe, {GenerateReportPath(), QString::number(QDateTime::currentSecsSinceEpoch())});
client->DumpAndCrash(ExceptionInfo);
return EXCEPTION_CONTINUE_SEARCH;
}
#elif defined(OS_LINUX)
bool LinuxExceptionHandler(int, siginfo_t*, ucontext_t*)
{
QString crash_handler_exe = QDir(qApp->applicationDirPath()).filePath(QStringLiteral("olive-crashhandler"));
QProcess::startDetached(crash_handler_exe, {GenerateReportPath(), QString::number(QDateTime::currentSecsSinceEpoch())});
// Returning false signals to Crashpad to proceed with its own exception handling
return false;
}
#endif
bool InitializeCrashpad()
{
QString exe_dir = QCoreApplication::applicationDirPath();
#ifdef OS_WIN
base::FilePath handler(QSTRING_TO_BASE_STRING(QDir(exe_dir).filePath(QStringLiteral("crashpad_handler.exe"))));
#else
// FIXME: On Linux, probably should put this in a subdir so that it doesn't conflict with
// anything else in /usr/bin
#ifdef Q_OS_WINDOWS
base::FilePath handler(TO_BASE_STRING_TYPE(QDir(exe_dir).filePath(QStringLiteral("crashpad_handler.exe"))));
#else
base::FilePath handler(TO_BASE_STRING_TYPE(QDir(exe_dir).filePath(QStringLiteral("crashpad_handler"))));
base::FilePath handler(QSTRING_TO_BASE_STRING(QDir(exe_dir).filePath(QStringLiteral("crashpad_handler"))));
#endif
base::FilePath reports_dir(TO_BASE_STRING_TYPE(QDir(OLIVE_NAMESPACE::FileFunctions::GetTempFilePath()).filePath("reports")));
base::FilePath reports_dir = GenerateReportPathForCrashpad();
base::FilePath metrics_dir(TO_BASE_STRING_TYPE(QDir(OLIVE_NAMESPACE::FileFunctions::GetTempFilePath()).filePath("metrics")));
std::string url = "https://olivevideoeditor.org/crashpad/report.php";
base::FilePath metrics_dir(QSTRING_TO_BASE_STRING(QDir(OLIVE_NAMESPACE::FileFunctions::GetTempFilePath()).filePath(QStringLiteral("metrics"))));
// Metadata that will be posted to the server with the crash report map
std::map<std::string, std::string> annotations;
@@ -105,19 +97,22 @@ bool InitializeCrashpad()
std::unique_ptr<crashpad::CrashReportDatabase> database = crashpad::CrashReportDatabase::Initialize(reports_dir);
if (database == NULL) return false;
// Enable automated crash uploads
// Disable automated crash uploads
crashpad::Settings *settings = database->GetSettings();
if (settings == NULL) return false;
settings->SetUploadsEnabled(true);
settings->SetUploadsEnabled(false);
// Start crash handler
client = new crashpad::CrashpadClient();
bool status = client->StartHandler(handler, reports_dir, metrics_dir,
url, annotations, arguments, true, true);
"https://olivevideoeditor.org/crashpad/report.php",
annotations, arguments, true, true);
// Override Crashpad exception filter with our own
#ifdef Q_OS_WINDOWS
#if defined(OS_WIN)
SetUnhandledExceptionFilter(Win32ExceptionHandler);
#elif defined(OS_LINUX)
crashpad::CrashpadClient::SetFirstChanceExceptionHandler(LinuxExceptionHandler);
#endif
return status;
-1
View File
@@ -23,7 +23,6 @@
#ifdef USE_CRASHPAD
#include <client/crashpad_client.h>
#include <client/crash_report_database.h>
#include <client/settings.h>
@@ -18,15 +18,23 @@
***/
#ifndef CRASHHANDLER_H
#define CRASHHANDLER_H
#ifndef CRASHPADUTILS_H
#define CRASHPADUTILS_H
#include "common/define.h"
#include <client/crashpad_client.h>
OLIVE_NAMESPACE_ENTER
// Copied from base::FilePath to match its macro
#if defined(OS_POSIX)
// On most platforms, native pathnames are char arrays, and the encoding
// may or may not be specified. On Mac OS X, native pathnames are encoded
// in UTF-8.
#define QSTRING_TO_BASE_STRING(x) x.toStdString()
#define BASE_STRING_TO_QSTRING(x) QString::fromStdString(x)
#elif defined(OS_WIN)
// On Windows, for Unicode-aware applications, native pathnames are wchar_t
// arrays encoded in UTF-16.
#define QSTRING_TO_BASE_STRING(x) x.toStdWString()
#define BASE_STRING_TO_QSTRING(x) QString::fromStdWString(x)
#endif // OS_WIN
void crash_handler(int sig);
OLIVE_NAMESPACE_EXIT
#endif // CRASHHANDLER_H
#endif // CRASHPADUTILS_H
+148 -33
View File
@@ -20,66 +20,181 @@
#include "crashhandler.h"
#include <QApplication>
#include <QDir>
#include <QFile>
#include <QFontDatabase>
#include <QLabel>
#include <QDialogButtonBox>
#include <QHttpMultiPart>
#include <QMessageBox>
#include <QNetworkAccessManager>
#include <QProcess>
#include <QScrollBar>
#include <QTextEdit>
#include <QThread>
#include <QTimer>
#include <QVBoxLayout>
#include "common/crashpadutils.h"
OLIVE_NAMESPACE_ENTER
CrashHandlerDialog::CrashHandlerDialog(const char *log_file)
CrashHandlerDialog::CrashHandlerDialog(const char *report_dir, const char* crash_time)
{
setWindowTitle(tr("Olive"));
crash_time_ = QString(crash_time).toULongLong();
report_dir_ = report_dir;
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.")));
layout->addWidget(new QLabel(tr("We're sorry, Olive has crashed. Please help us fix it by "
"sending an error report.")));
QTextEdit* edit = new QTextEdit();
edit->setReadOnly(true);
layout->addWidget(edit);
summary_edit_ = new QTextEdit();
summary_edit_->setPlaceholderText(tr("Describe what you were doing in as much detail as "
"possible. If you can, provide steps to reproduce this crash."));
edit->append(QStringLiteral("Build Environment: %1 (%2)").arg(QSysInfo::buildCpuArchitecture(), QSysInfo::buildAbi()));
edit->append(QStringLiteral("Run Environment: %1").arg(QSysInfo::currentCpuArchitecture()));
edit->append(QStringLiteral("Kernel: %1 %2").arg(QSysInfo::kernelType(), QSysInfo::kernelVersion()));
edit->append(QStringLiteral("System: %1 (%2 %3)").arg(QSysInfo::prettyProductName(), QSysInfo::productType(), QSysInfo::productVersion()));
edit->append(QString());
layout->addWidget(summary_edit_);
QDialogButtonBox* buttons = new QDialogButtonBox();
layout->addWidget(new QLabel(tr("Crash Report:")));
// FIXME: Implement auto-reporting
//buttons->addButton(tr("Send Error Report"), QDialogButtonBox::AcceptRole);
//buttons->addButton(tr("Don't Send"), QDialogButtonBox::RejectRole);
buttons->addButton(QDialogButtonBox::Ok);
crash_report_ = new QTextEdit();
crash_report_->setReadOnly(true);
crash_report_->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
layout->addWidget(crash_report_);
connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
layout->addWidget(buttons);
QHBoxLayout* btn_layout = new QHBoxLayout();
btn_layout->setMargin(0);
btn_layout->addStretch();
QFile log(log_file);
if (log.open(QFile::ReadOnly | QFile::Text)) {
edit->append(log.readAll());
send_report_btn_ = new QPushButton(tr("Send Error Report"));
connect(send_report_btn_, &QPushButton::clicked, this, &CrashHandlerDialog::SendErrorReport);
btn_layout->addWidget(send_report_btn_);
QMetaObject::invokeMethod(edit->verticalScrollBar(),
"setValue",
Qt::QueuedConnection,
Q_ARG(int, 0));
dont_send_btn_ = new QPushButton(tr("Don't Send"));
connect(dont_send_btn_, &QPushButton::clicked, this, &CrashHandlerDialog::reject);
btn_layout->addWidget(dont_send_btn_);
log.close();
layout->addLayout(btn_layout);
crash_report_->setEnabled(false);
send_report_btn_->setEnabled(false);
crash_report_->setText(tr("Waiting for crash report to be generated..."));
AttemptToFindReport();
}
void CrashHandlerDialog::SetGUIObjectsEnabled(bool e)
{
summary_edit_->setEnabled(e);
crash_report_->setEnabled(e);
send_report_btn_->setEnabled(e);
dont_send_btn_->setEnabled(e);
}
void CrashHandlerDialog::GenerateReport()
{
QProcess* p = new QProcess();
connect(p, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, &CrashHandlerDialog::ReadProcessFinished);
connect(p, &QProcess::readyReadStandardOutput, this, &CrashHandlerDialog::ReadProcessHasData);
QString stackwalk_filename;
#if defined(OS_WIN)
stackwalk_filename = QStringLiteral("minidump_stackwalk.exe");
#else
stackwalk_filename = QStringLiteral("minidump_stackwalk");
#endif
QString stackwalk_bin = QDir(qApp->applicationDirPath()).filePath(stackwalk_filename);
p->start(stackwalk_bin, {report_filename_});
crash_report_->setText(QStringLiteral("Trying to run: %1").arg(stackwalk_bin));
}
void CrashHandlerDialog::ReplyFinished(QNetworkReply* reply)
{
if (reply->error() == QNetworkReply::NoError) {
// Close dialog
QDialog::accept();
} else {
QMessageBox::critical(this, tr("Upload Failed"),
tr("Failed to send error report. Please try again later."),
QMessageBox::Ok);
SetGUIObjectsEnabled(true);
}
}
void CrashHandlerDialog::accept()
void CrashHandlerDialog::AttemptToFindReport()
{
QDialog::accept();
// Retrieve reports from Crashpad database
std::unique_ptr<crashpad::CrashReportDatabase> database = crashpad::CrashReportDatabase::Initialize(base::FilePath(QSTRING_TO_BASE_STRING(QString(report_dir_))));
std::vector<crashpad::CrashReportDatabase::Report> reports;
database->GetCompletedReports(&reports);
// Find report that was made after the crash time
foreach (const crashpad::CrashReportDatabase::Report& report, reports) {
if (report.creation_time >= crash_time_) {
report_filename_ = BASE_STRING_TO_QSTRING(report.file_path.value());
break;
}
}
// If we found it, use it, otherwise wait a second and try again
if (report_filename_.isEmpty()) {
// Couldn't find report, try again in one second
QTimer::singleShot(500, this, &CrashHandlerDialog::AttemptToFindReport);
} else {
GenerateReport();
}
}
void CrashHandlerDialog::reject()
void CrashHandlerDialog::ReadProcessHasData()
{
QDialog::reject();
report_data_.append(static_cast<QProcess*>(sender())->readAllStandardOutput());
}
void CrashHandlerDialog::ReadProcessFinished()
{
SetGUIObjectsEnabled(true);
crash_report_->setText(report_data_);
delete sender();
}
void CrashHandlerDialog::SendErrorReport()
{
SetGUIObjectsEnabled(false);
QNetworkAccessManager* manager = new QNetworkAccessManager();
connect(manager, &QNetworkAccessManager::finished, this, &CrashHandlerDialog::ReplyFinished);
QNetworkRequest request;
request.setSslConfiguration(QSslConfiguration::defaultConfiguration());
request.setUrl(QStringLiteral("https://olivevideoeditor.org/crashpad/report.php"));
// Create HTTP form
QHttpMultiPart* multipart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
// Create description section
QHttpPart desc_part;
desc_part.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("text/plain"));
desc_part.setHeader(QNetworkRequest::ContentDispositionHeader, QStringLiteral("form-data; name=\"description\""));
desc_part.setBody(summary_edit_->toPlainText().toUtf8());
multipart->append(desc_part);
// Create file section
QHttpPart file_part;
file_part.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/octet-stream"));
file_part.setHeader(QNetworkRequest::ContentDispositionHeader, QStringLiteral("form-data; name=\"upload_file_minidump\"; filename=\"%1\"")
.arg(QFileInfo(report_filename_).fileName()));
QFile* file = new QFile(report_filename_);
file->open(QFile::ReadOnly);
file_part.setBodyDevice(file);
file->setParent(multipart); // Delete file with multipart
multipart->append(file_part);
manager->post(request, multipart);
}
OLIVE_NAMESPACE_EXIT
+36 -4
View File
@@ -21,7 +21,12 @@
#ifndef CRASHHANDLERDIALOG_H
#define CRASHHANDLERDIALOG_H
#include <client/crash_report_database.h>
#include <QDialog>
#include <QDialogButtonBox>
#include <QNetworkReply>
#include <QPushButton>
#include <QTextEdit>
#include "common/define.h"
@@ -31,12 +36,39 @@ class CrashHandlerDialog : public QDialog
{
Q_OBJECT
public:
CrashHandlerDialog(const char* log_file);
CrashHandlerDialog(const char* report_dir, const char* crash_time);
public slots:
virtual void accept() override;
private:
void SetGUIObjectsEnabled(bool e);
virtual void reject() override;
void GenerateReport();
QTextEdit* summary_edit_;
QTextEdit* crash_report_;
QPushButton* send_report_btn_;
QPushButton* dont_send_btn_;
QString report_filename_;
time_t crash_time_;
QString report_dir_;
QByteArray report_data_;
private slots:
void ReplyFinished(QNetworkReply *reply);
void AttemptToFindReport();
void ReadProcessHasData();
void ReadProcessFinished();
void SendErrorReport();
};
+2 -2
View File
@@ -24,13 +24,13 @@
int main(int argc, char *argv[])
{
if (argc < 2) {
if (argc < 3) {
return 1;
}
QApplication a(argc, argv);
OLIVE_NAMESPACE::CrashHandlerDialog chd(argv[1]);
OLIVE_NAMESPACE::CrashHandlerDialog chd(argv[1], argv[2]);
chd.open();
return a.exec();
+4
View File
@@ -79,6 +79,10 @@ foreach (COMPONENT ${_crashpad_components})
list(APPEND CRASHPAD_LIBRARIES ${CRASHPAD_${UPPERCOMPONENT}_LIB})
endforeach()
if (UNIX AND NOT APPLE)
list(APPEND CRASHPAD_LIBRARIES ${CMAKE_DL_LIBS} Threads::Threads)
endif()
find_package_handle_standard_args(GoogleCrashpad
REQUIRED_VARS
CRASHPAD_LIBRARIES