From a6738e32655a7268cca611624050f14af2ba7990 Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 9 Apr 2018 08:06:02 -0500 Subject: [PATCH 1/3] Added boost stacktrace to segfault handler --- CMakeLists.txt | 1 + include/fc/stacktrace.hpp | 16 +++++++++++++ src/stacktrace.cpp | 43 +++++++++++++++++++++++++++++++++ tests/CMakeLists.txt | 1 + tests/stacktrace_test.cpp | 50 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 111 insertions(+) create mode 100644 include/fc/stacktrace.hpp create mode 100644 src/stacktrace.cpp create mode 100644 tests/stacktrace_test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c5ed73395..90f7bfa31 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -221,6 +221,7 @@ set( fc_sources src/asio.cpp src/string.cpp src/shared_ptr.cpp + src/stacktrace.cpp src/time.cpp src/utf8.cpp src/io/iostream.cpp diff --git a/include/fc/stacktrace.hpp b/include/fc/stacktrace.hpp new file mode 100644 index 000000000..1918b0cbb --- /dev/null +++ b/include/fc/stacktrace.hpp @@ -0,0 +1,16 @@ +// stacktrace.h (c) 2008, Timo Bingmann from http://idlebox.net/ +// published under the WTFPL v2.0 + +// Downloaded from http://panthema.net/2008/0901-stacktrace-demangled/ +// and modified for C++ and FC by Steemit, Inc. + +#pragma once + +#include + +namespace fc { + +void print_stacktrace(std::ostream& out); +void print_stacktrace_on_segfault(); + +} diff --git a/src/stacktrace.cpp b/src/stacktrace.cpp new file mode 100644 index 000000000..e6424be6a --- /dev/null +++ b/src/stacktrace.cpp @@ -0,0 +1,43 @@ +// +// A stacktrace handler for bitshares +// + +#include +#include + +// only include stacktrace stuff if boost >= 1.65 +#if BOOST_VERSION / 100000 >= 1 && ((BOOST_VERSION / 100) % 1000) >= 65 +#include + +namespace fc +{ + +static void segfault_signal_handler(int signum) +{ + ::signal(signum, SIG_DFL); + std::stringstream ss; + ss << boost::stacktrace::stacktrace(); + elog(ss.str()); + ::raise(SIGABRT); +} + +void print_stacktrace_on_segfault() +{ + ::signal(SIGSEGV, &segfault_signal_handler); +} + +void print_stacktrace(std::ostream& out) +{ + out << boost::stacktrace::stacktrace(); +} + +} +#else + +namespace fc +{ +void print_stacktrace_on_segfault() {} +void print_stacktrace(std::ostream& out) {} +} + +#endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b1d582112..f2c058082 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -57,6 +57,7 @@ add_executable( all_tests all_tests.cpp bloom_test.cpp real128_test.cpp serialization_test.cpp + stacktrace_test.cpp time_test.cpp utf8_test.cpp variant_test.cpp diff --git a/tests/stacktrace_test.cpp b/tests/stacktrace_test.cpp new file mode 100644 index 000000000..baafa7669 --- /dev/null +++ b/tests/stacktrace_test.cpp @@ -0,0 +1,50 @@ +#include + +#include +#include +#include + +BOOST_AUTO_TEST_SUITE(fc_stacktrace) + +BOOST_AUTO_TEST_CASE(stacktrace_test) +{ + // print the stack trace + std::stringstream ss; + fc::print_stacktrace(ss); + std::string results = ss.str(); +#if BOOST_VERSION / 100000 >= 1 && ((BOOST_VERSION / 100) % 1000) >= 65 + BOOST_CHECK(!results.empty()); + BOOST_CHECK(results.find("fc::print_stacktrace") != std::string::npos); +#else + BOOST_CHECK(results.empty()); +#endif +} + +BOOST_AUTO_TEST_CASE(threaded_stacktrace_test) +{ + fc::thread test_thread("a_thread"); + std::string results = test_thread.async( + [] ()->std::string { + // cause a pause + for(int i = 0; i < 10000; i++); + std::stringstream ss; + fc::print_stacktrace(ss); + return ss.str(); + } + ).wait(); +#if BOOST_VERSION / 100000 >= 1 && ((BOOST_VERSION / 100) % 1000) >= 65 + BOOST_CHECK(!results.empty()); + BOOST_CHECK(results.find("fc::print_stacktrace") != std::string::npos); +#else + BOOST_CHECK(results.empty()); +#endif +} + +/* this test causes a segfault on purpose to test the event handler +BOOST_AUTO_TEST_CASE(cause_segfault) +{ + fc::print_stacktrace_on_segfault(); + ::raise(SIGSEGV); +} +*/ +BOOST_AUTO_TEST_SUITE_END() From 133fe62048ede4c8c3d5b16c8963c4b87cd0203c Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 9 Apr 2018 08:59:58 -0500 Subject: [PATCH 2/3] Add comment to clarify 2 sections of code. --- src/stacktrace.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/stacktrace.cpp b/src/stacktrace.cpp index e6424be6a..ab4e4d03e 100644 --- a/src/stacktrace.cpp +++ b/src/stacktrace.cpp @@ -33,7 +33,8 @@ void print_stacktrace(std::ostream& out) } #else - +// Stacktrace output requires Boost 1.65 or above. +// Therefore calls to these methods do nothing. namespace fc { void print_stacktrace_on_segfault() {} From 7db8176624ac1abaa5d3b4f45c392812d64d101c Mon Sep 17 00:00:00 2001 From: John Jones Date: Mon, 9 Apr 2018 17:29:57 -0500 Subject: [PATCH 3/3] Moved headers within #if macro for cleanliness --- src/stacktrace.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/stacktrace.cpp b/src/stacktrace.cpp index ab4e4d03e..2504bb10e 100644 --- a/src/stacktrace.cpp +++ b/src/stacktrace.cpp @@ -1,12 +1,12 @@ // // A stacktrace handler for bitshares // - -#include -#include +#include // only include stacktrace stuff if boost >= 1.65 #if BOOST_VERSION / 100000 >= 1 && ((BOOST_VERSION / 100) % 1000) >= 65 +#include +#include #include namespace fc