Added boost stacktrace to segfault handler

This commit is contained in:
John Jones 2018-04-09 08:06:02 -05:00
parent 18640e46e3
commit a6738e3265
5 changed files with 111 additions and 0 deletions

View file

@ -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

16
include/fc/stacktrace.hpp Normal file
View file

@ -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 <iostream>
namespace fc {
void print_stacktrace(std::ostream& out);
void print_stacktrace_on_segfault();
}

43
src/stacktrace.cpp Normal file
View file

@ -0,0 +1,43 @@
//
// A stacktrace handler for bitshares
//
#include <signal.h>
#include <fc/log/logger.hpp>
// only include stacktrace stuff if boost >= 1.65
#if BOOST_VERSION / 100000 >= 1 && ((BOOST_VERSION / 100) % 1000) >= 65
#include <boost/stacktrace.hpp>
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

View file

@ -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

50
tests/stacktrace_test.cpp Normal file
View file

@ -0,0 +1,50 @@
#include <boost/test/unit_test.hpp>
#include <signal.h>
#include <fc/stacktrace.hpp>
#include <fc/thread/thread.hpp>
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()