From c5d6200c96d6478e2ff0a7be5fddf001d4cc41c1 Mon Sep 17 00:00:00 2001 From: Soeren Apel Date: Fri, 30 Mar 2018 17:56:28 +0200 Subject: [PATCH] Main: Create human-readable stack trace and notify user --- main.cpp | 69 +++++++++++++++++++++++++++++++++++++++++-- pv/globalsettings.cpp | 5 ++++ pv/globalsettings.hpp | 1 + 3 files changed, 73 insertions(+), 2 deletions(-) diff --git a/main.cpp b/main.cpp index d2512331..cebeca37 100644 --- a/main.cpp +++ b/main.cpp @@ -22,12 +22,18 @@ #endif #include -#include - +#include #include +#include + +#include #include +#include +#include +#include #include +#include #ifdef ENABLE_SIGNALS #include "signalhandler.hpp" @@ -61,6 +67,8 @@ Q_IMPORT_PLUGIN(QSvgPlugin) #endif using std::exception; +using std::ifstream; +using std::ofstream; using std::shared_ptr; using std::string; @@ -73,6 +81,60 @@ void signal_handler(int signum) boost::stacktrace::safe_dump_to(stacktrace_filename.toLocal8Bit().data()); ::raise(SIGABRT); } + +void process_stacktrace(QString temp_path) +{ + const QString stacktrace_outfile = temp_path + "/pv_stacktrace.txt"; + + ifstream ifs(stacktrace_filename.toLocal8Bit().data()); + ofstream ofs(stacktrace_outfile.toLocal8Bit().data(), + ofstream::out | ofstream::trunc); + + boost::stacktrace::stacktrace st = + boost::stacktrace::stacktrace::from_dump(ifs); + ofs << st; + + ofs.close(); + ifs.close(); + + QFile f(stacktrace_outfile); + f.open(QFile::ReadOnly | QFile::Text); + QTextStream fs(&f); + QString stacktrace = fs.readAll(); + stacktrace = stacktrace.trimmed().replace('\n', "
"); + + qDebug() << QObject::tr("Stack trace of previous crash:"); + qDebug() << "---------------------------------------------------------"; + // Note: qDebug() prints quotation marks for QString output, so we feed it char* + qDebug() << stacktrace.toLocal8Bit().data(); + qDebug() << "---------------------------------------------------------"; + + f.close(); + + // Remove stack trace so we don't process it again the next time we run + QFile::remove(stacktrace_filename.toLocal8Bit().data()); + + // Show notification dialog if permitted + pv::GlobalSettings settings; + if (settings.value(pv::GlobalSettings::Key_Log_NotifyOfStacktrace).toBool()) { + QCheckBox *cb = new QCheckBox(QObject::tr("Don't show this message again")); + + QMessageBox msgbox; + msgbox.setText(QObject::tr("When %1 last crashed, it created a stack trace.\n" \ + "A human-readable form has been saved to disk and was written to " \ + "the log. You may access it from the settings dialog.").arg(PV_TITLE)); + msgbox.setIcon(QMessageBox::Icon::Information); + msgbox.addButton(QMessageBox::Ok); + msgbox.setCheckBox(cb); + + QObject::connect(cb, &QCheckBox::stateChanged, [](int state){ + pv::GlobalSettings settings; + settings.setValue(pv::GlobalSettings::Key_Log_NotifyOfStacktrace, + !state); }); + + msgbox.exec(); + } +} #endif void usage() @@ -218,6 +280,9 @@ int main(int argc, char *argv[]) ::signal(SIGSEGV, &signal_handler); ::signal(SIGABRT, &signal_handler); + + if (QFileInfo::exists(stacktrace_filename)) + process_stacktrace(temp_path); #endif #ifdef ANDROID diff --git a/pv/globalsettings.cpp b/pv/globalsettings.cpp index 93608290..0aaffdd9 100644 --- a/pv/globalsettings.cpp +++ b/pv/globalsettings.cpp @@ -40,6 +40,7 @@ const QString GlobalSettings::Key_View_DefaultDivHeight = "View_DefaultDivHeight const QString GlobalSettings::Key_View_DefaultLogicHeight = "View_DefaultLogicHeight"; const QString GlobalSettings::Key_Dec_InitialStateConfigurable = "Dec_InitialStateConfigurable"; const QString GlobalSettings::Key_Log_BufferSize = "Log_BufferSize"; +const QString GlobalSettings::Key_Log_NotifyOfStacktrace = "Log_NotifyOfStacktrace"; vector GlobalSettings::callbacks_; bool GlobalSettings::tracking_ = false; @@ -76,6 +77,10 @@ void GlobalSettings::set_defaults_where_needed() // Default to 500 lines of backlog if (!contains(Key_Log_BufferSize)) setValue(Key_Log_BufferSize, 500); + + // Notify user of existing stack trace by default + if (!contains(Key_Log_NotifyOfStacktrace)) + setValue(Key_Log_NotifyOfStacktrace, true); } void GlobalSettings::add_change_handler(GlobalSettingsInterface *cb) diff --git a/pv/globalsettings.hpp b/pv/globalsettings.hpp index eda3e03a..51212b02 100644 --- a/pv/globalsettings.hpp +++ b/pv/globalsettings.hpp @@ -57,6 +57,7 @@ public: static const QString Key_View_DefaultLogicHeight; static const QString Key_Dec_InitialStateConfigurable; static const QString Key_Log_BufferSize; + static const QString Key_Log_NotifyOfStacktrace; enum ConvThrDispMode { ConvThrDispMode_None = 0, -- 2.30.2