]> sigrok.org Git - pulseview.git/commitdiff
Add boost::stacktrace support
authorSoeren Apel <redacted>
Tue, 27 Mar 2018 14:25:17 +0000 (16:25 +0200)
committerSoeren Apel <redacted>
Thu, 29 Mar 2018 21:29:57 +0000 (23:29 +0200)
CMakeLists.txt
main.cpp
pv/application.cpp

index 09f28a19c9ccf1f95e0513d8b38919d6bc32ea85..1994a130a09f9e4daf1335ba35ecca59ec659abb 100644 (file)
@@ -32,6 +32,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMake")
 
 option(DISABLE_WERROR "Build without -Werror" FALSE)
 option(ENABLE_SIGNALS "Build with UNIX signals" TRUE)
+option(ENABLE_STACKTRACE "Enable stack trace when crashing" FALSE)
 option(ENABLE_DECODE "Build with libsigrokdecode" TRUE)
 option(ENABLE_TESTS "Enable unit tests" TRUE)
 option(STATIC_PKGDEPS_LIBS "Statically link to (pkg-config) libraries" FALSE)
@@ -90,7 +91,12 @@ set(BOOSTCOMPS filesystem serialization system)
 if(ENABLE_TESTS)
        list(APPEND BOOSTCOMPS unit_test_framework)
 endif()
-find_package(Boost 1.55 COMPONENTS ${BOOSTCOMPS} REQUIRED)
+
+if(ENABLE_STACKTRACE)
+       find_package(Boost 1.65.1 COMPONENTS ${BOOSTCOMPS} REQUIRED)
+else()
+       find_package(Boost 1.55 COMPONENTS ${BOOSTCOMPS} REQUIRED)
+endif()
 
 # Find the platform's thread library (needed for C++11 threads).
 # This will set ${CMAKE_THREAD_LIBS_INIT} to the correct, OS-specific value.
@@ -391,6 +397,10 @@ if(ENABLE_SIGNALS)
        add_definitions(-DENABLE_SIGNALS)
 endif()
 
+if(ENABLE_STACKTRACE)
+       add_definitions(-DENABLE_STACKTRACE)
+endif()
+
 #===============================================================================
 #= Global Include Directories
 #-------------------------------------------------------------------------------
@@ -442,6 +452,11 @@ if(WIN32)
        list(APPEND PULSEVIEW_LINK_LIBS ${QT5ALL_LDFLAGS})
 endif()
 
+if(ENABLE_STACKTRACE)
+       # Needed to resolve dladdr.
+       list(APPEND PULSEVIEW_LINK_LIBS "-ldl")
+endif()
+
 if(ANDROID)
        list(APPEND PULSEVIEW_LINK_LIBS "-llog")
 endif()
index 1e214e03f97df04c1f694b971ca25df0a36cc3eb..640168ff79b8c316f7638cfa423e5625cffe0251 100644 (file)
--- a/main.cpp
+++ b/main.cpp
 #include "signalhandler.hpp"
 #endif
 
+#ifdef ENABLE_STACKTRACE
+#include <signal.h>
+#include <boost/stacktrace.hpp>
+#include <QStandardPaths>
+#endif
+
 #include "pv/application.hpp"
 #include "pv/devicemanager.hpp"
 #include "pv/mainwindow.hpp"
 #include "pv/session.hpp"
+
 #ifdef ANDROID
 #include <libsigrokandroidutils/libsigrokandroidutils.h>
 #include "android/assetreader.hpp"
@@ -55,6 +62,17 @@ using std::exception;
 using std::shared_ptr;
 using std::string;
 
+#if ENABLE_STACKTRACE
+QString stacktrace_filename;
+
+void signal_handler(int signum)
+{
+       ::signal(signum, SIG_DFL);
+       boost::stacktrace::safe_dump_to(stacktrace_filename.toLocal8Bit().data());
+       ::raise(SIGABRT);
+}
+#endif
+
 void usage()
 {
        fprintf(stdout,
@@ -175,6 +193,16 @@ int main(int argc, char *argv[])
        context = sigrok::Context::create();
        pv::Session::sr_context = context;
 
+#if ENABLE_STACKTRACE
+       QString temp_path = QStandardPaths::standardLocations(
+               QStandardPaths::TempLocation).at(0);
+       stacktrace_filename = temp_path + "/pv_stacktrace.dmp";
+       qDebug() << "Stack trace file is" << stacktrace_filename;
+
+       ::signal(SIGSEGV, &signal_handler);
+       ::signal(SIGABRT, &signal_handler);
+#endif
+
 #ifdef ANDROID
        context->set_resource_reader(&asset_reader);
 #endif
@@ -191,44 +219,44 @@ int main(int argc, char *argv[])
                srd_decoder_load_all();
 #endif
 
+#ifndef ENABLE_STACKTRACE
                try {
-                       // Create the device manager, initialise the drivers
-                       pv::DeviceManager device_manager(context, driver, do_scan);
+#endif
 
-                       // Initialise the main window
-                       pv::MainWindow w(device_manager);
-                       w.show();
+               // Create the device manager, initialise the drivers
+               pv::DeviceManager device_manager(context, driver, do_scan);
 
-                       if (restore_sessions)
-                               w.restore_sessions();
+               // Initialise the main window
+               pv::MainWindow w(device_manager);
+               w.show();
 
-                       if (!open_file.empty())
-                               w.add_session_with_file(open_file, open_file_format);
-                       else
-                               w.add_default_session();
+               if (restore_sessions)
+                       w.restore_sessions();
+
+               if (!open_file.empty())
+                       w.add_session_with_file(open_file, open_file_format);
+               else
+                       w.add_default_session();
 
 #ifdef ENABLE_SIGNALS
-                       if (SignalHandler::prepare_signals()) {
-                               SignalHandler *const handler =
-                                       new SignalHandler(&w);
-                               QObject::connect(handler,
-                                       SIGNAL(int_received()),
-                                       &w, SLOT(close()));
-                               QObject::connect(handler,
-                                       SIGNAL(term_received()),
-                                       &w, SLOT(close()));
-                       } else {
-                               qWarning() <<
-                                       "Could not prepare signal handler.";
-                       }
+               if (SignalHandler::prepare_signals()) {
+                       SignalHandler *const handler = new SignalHandler(&w);
+                       QObject::connect(handler, SIGNAL(int_received()),
+                               &w, SLOT(close()));
+                       QObject::connect(handler, SIGNAL(term_received()),
+                               &w, SLOT(close()));
+               } else
+                       qWarning() << "Could not prepare signal handler.";
 #endif
 
-                       // Run the application
-                       ret = a.exec();
+               // Run the application
+               ret = a.exec();
 
+#ifndef ENABLE_STACKTRACE
                } catch (exception& e) {
-                       qDebug() << e.what();
+                       qDebug() << "Exception:" << e.what();
                }
+#endif
 
 #ifdef ENABLE_DECODE
                // Destroy libsigrokdecode
index 383b5c23d29737c6c14ebb537b4756a57ee83139..c16c9c4b7c757e3a4312316bb69edb668ef2615e 100644 (file)
 #include "application.hpp"
 #include "config.h"
 
-#include <iostream>
+#include <typeinfo>
+
+#include <QDebug>
+
+#ifdef ENABLE_STACKTRACE
+#include <boost/stacktrace.hpp>
+#endif
 
-using std::cerr;
-using std::endl;
 using std::exception;
 
 Application::Application(int &argc, char* argv[]) :
@@ -40,8 +44,13 @@ bool Application::notify(QObject *receiver, QEvent *event)
        try {
                return QApplication::notify(receiver, event);
        } catch (exception& e) {
-               cerr << "Caught exception: " << e.what() << endl;
+               qDebug().nospace() << "Caught exception of type " << \
+                       typeid(e).name() << " (" << e.what() << ")";
+#ifdef ENABLE_STACKTRACE
+               throw e;
+#else
                exit(1);
+#endif
                return false;
        }
 }