#endif
#include <cstdint>
-#include <libsigrokcxx/libsigrokcxx.hpp>
-
+#include <fstream>
#include <getopt.h>
+#include <libsigrokcxx/libsigrokcxx.hpp>
+
+#include <QCheckBox>
#include <QDebug>
+#include <QFile>
+#include <QFileInfo>
+#include <QMessageBox>
#include <QSettings>
+#include <QTextStream>
#ifdef ENABLE_SIGNALS
#include "signalhandler.hpp"
#endif
using std::exception;
+using std::ifstream;
+using std::ofstream;
using std::shared_ptr;
using std::string;
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', "<br />");
+
+ 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()
::signal(SIGSEGV, &signal_handler);
::signal(SIGABRT, &signal_handler);
+
+ if (QFileInfo::exists(stacktrace_filename))
+ process_stacktrace(temp_path);
#endif
#ifdef ANDROID
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<GlobalSettingsInterface*> GlobalSettings::callbacks_;
bool GlobalSettings::tracking_ = false;
// 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)