summaryrefslogtreecommitdiff
path: root/gnuradio-runtime/lib/terminate_handler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gnuradio-runtime/lib/terminate_handler.cc')
-rw-r--r--gnuradio-runtime/lib/terminate_handler.cc147
1 files changed, 147 insertions, 0 deletions
diff --git a/gnuradio-runtime/lib/terminate_handler.cc b/gnuradio-runtime/lib/terminate_handler.cc
new file mode 100644
index 0000000000..ed3b1d93b4
--- /dev/null
+++ b/gnuradio-runtime/lib/terminate_handler.cc
@@ -0,0 +1,147 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2018 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <pmt/pmt.h>
+#include <boost/thread.hpp>
+#include <exception>
+#include <iostream>
+#include <regex>
+#include <stdexcept>
+
+#include <cxxabi.h>
+
+#ifdef HAVE_LIBUNWIND
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#include <cstdio>
+#include <cstdlib>
+#endif
+
+namespace gr {
+
+#ifdef HAVE_LIBUNWIND
+void print_backtrace()
+{
+ unw_cursor_t cursor;
+ unw_context_t context;
+
+ // Initialize cursor to current frame for local unwinding.
+ unw_getcontext(&context);
+ unw_init_local(&cursor, &context);
+
+ // Unwind frames one by one, going up the frame stack.
+ while (unw_step(&cursor) > 0) {
+ unw_word_t offset, pc;
+ unw_get_reg(&cursor, UNW_REG_IP, &pc);
+ if (pc == 0) {
+ break;
+ }
+ std::fprintf(stderr, "0x%lx:", pc);
+
+ char sym[256];
+ if (unw_get_proc_name(&cursor, sym, sizeof(sym), &offset) == 0) {
+ char* nameptr = sym;
+ int status;
+ char* demangled = abi::__cxa_demangle(sym, nullptr, nullptr, &status);
+ if (status == 0) {
+ nameptr = demangled;
+ }
+ std::fprintf(stderr, " (%s+0x%lx)\n", nameptr, offset);
+ std::free(demangled);
+ } else {
+ std::fprintf(stderr,
+ " -- error: unable to obtain symbol name for this frame\n");
+ }
+ }
+}
+#endif
+
+void terminate_handler_impl()
+{
+ std::cerr << "terminate reached from thread id: " << boost::this_thread::get_id();
+ try {
+ std::exception_ptr eptr = std::current_exception();
+ if (eptr) {
+ std::rethrow_exception(eptr);
+ }
+ } catch (const std::out_of_range& e) {
+ std::cerr << "Got std::out_of_range" << std::endl;
+ std::cerr << e.what() << std::endl;
+ } catch (const std::length_error& e) {
+ std::cerr << "Got std::length_error" << std::endl;
+ std::cerr << e.what() << std::endl;
+ } catch (const std::domain_error& e) {
+ std::cerr << "Got std::domain_error" << std::endl;
+ std::cerr << e.what() << std::endl;
+ } catch (const std::invalid_argument& e) {
+ std::cerr << "Got std::invalid_argument" << std::endl;
+ std::cerr << e.what() << std::endl;
+ } catch (const pmt::exception& e) {
+ std::cerr << "Got pmt::exception" << std::endl;
+ std::cerr << e.what() << std::endl;
+ } catch (const std::logic_error& e) {
+ std::cerr << "Got std::logic_error" << std::endl;
+ std::cerr << e.what() << std::endl;
+ } catch (const std::ios_base::failure& e) {
+ std::cerr << "Got std::ios_base::falure" << std::endl;
+ std::cerr << e.what() << std::endl;
+ } catch (const std::system_error& e) {
+ std::cerr << "Got std::system_error" << std::endl;
+ std::cerr << e.what() << std::endl;
+ } catch (const std::regex_error& e) {
+ std::cerr << "Got std::regex_error" << std::endl;
+ std::cerr << e.what() << std::endl;
+ } catch (const std::underflow_error& e) {
+ std::cerr << "Got std::underflow_error" << std::endl;
+ std::cerr << e.what() << std::endl;
+ } catch (const std::overflow_error& e) {
+ std::cerr << "Got std::overflow_error" << std::endl;
+ std::cerr << e.what() << std::endl;
+ } catch (const std::range_error& e) {
+ std::cerr << "Got std::range_error" << std::endl;
+ std::cerr << e.what() << std::endl;
+ } catch (const std::runtime_error& e) {
+ std::cerr << "Got std::runtime_error" << std::endl;
+ std::cerr << e.what() << std::endl;
+ } catch (const std::bad_typeid& e) {
+ std::cerr << "Got std::bad_typeid" << std::endl;
+ std::cerr << e.what() << std::endl;
+ } catch (const std::bad_cast& e) {
+ std::cerr << "Got std::bad_cast" << std::endl;
+ std::cerr << e.what() << std::endl;
+ } catch (const std::bad_weak_ptr& e) {
+ std::cerr << "Got std::bad_weak_ptr" << std::endl;
+ std::cerr << e.what() << std::endl;
+ } catch (const std::bad_function_call& e) {
+ std::cerr << "Got std::bad_function_call" << std::endl;
+ std::cerr << e.what() << std::endl;
+ } catch (const std::bad_array_new_length& e) {
+ std::cerr << "Got std::bad_array_new_length" << std::endl;
+ std::cerr << e.what() << std::endl;
+ } catch (const std::bad_alloc& e) {
+ std::cerr << "Got std::bad_alloc" << std::endl;
+ std::cerr << e.what() << std::endl;
+ } catch (const std::bad_exception& e) {
+ std::cerr << "Got std::bad_exception" << std::endl;
+ std::cerr << e.what() << std::endl;
+ } catch (const std::exception& e) {
+ std::cerr << "Got std::exception" << std::endl;
+ std::cerr << e.what() << std::endl;
+ } catch (...) {
+ std::cerr << "Got unknown exception" << std::endl;
+ }
+#ifdef HAVE_LIBUNWIND
+ // Use libunwind to print a backtrace
+ print_backtrace();
+#endif
+ std::abort();
+}
+
+void install_terminate_handler() { std::set_terminate(&terminate_handler_impl); }
+} // namespace gr