[DEV] add v1.66.0

This commit is contained in:
2018-01-12 21:47:58 +01:00
parent 87059bb1af
commit a97e9ae7d4
49032 changed files with 7668950 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
// Copyright Antony Polukhin, 2016-2017.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_ENABLE_ASSERT_HANDLER
#include <cstdlib> // std::exit
#include <boost/array.hpp>
BOOST_NOINLINE void foo(int i);
BOOST_NOINLINE void bar(int i);
BOOST_NOINLINE void bar(int i) {
boost::array<int, 5> a = {{101, 100, 123, 23, 32}};
if (i >= 0) {
foo(a[i]);
} else {
std::exit(1);
}
}
BOOST_NOINLINE void foo(int i) {
bar(--i);
}
namespace std { inline void ignore_abort(){ std::exit(0); } }
#define abort ignore_abort
//[getting_started_assert_handlers
// BOOST_ENABLE_ASSERT_DEBUG_HANDLER is defined for the whole project
#include <stdexcept> // std::logic_error
#include <iostream> // std::cerr
#include <boost/stacktrace.hpp>
namespace boost {
inline void assertion_failed_msg(char const* expr, char const* msg, char const* function, char const* /*file*/, long /*line*/) {
std::cerr << "Expression '" << expr << "' is false in function '" << function << "': " << (msg ? msg : "<...>") << ".\n"
<< "Backtrace:\n" << boost::stacktrace::stacktrace() << '\n';
std::abort();
}
inline void assertion_failed(char const* expr, char const* function, char const* file, long line) {
::boost::assertion_failed_msg(expr, 0 /*nullptr*/, function, file, line);
}
} // namespace boost
//]
int main() {
foo(5);
return 2;
}

View File

@@ -0,0 +1,35 @@
// Copyright Antony Polukhin, 2016-2017.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//[getting_started_debug_function
#include <signal.h> // ::signal
#include <boost/stacktrace/frame.hpp>
#include <iostream> // std::cerr
#include <cstdlib> // std::exit
void print_signal_handler_and_exit() {
typedef void(*function_t)(int);
function_t old_signal_function = ::signal(SIGSEGV, SIG_DFL);
boost::stacktrace::frame f(old_signal_function);
std::cout << f << std::endl;
std::exit(0);
}
//]
void my_signal_handler(int /*signum*/) {
std::exit(1);
}
int main() {
::signal(SIGSEGV, &my_signal_handler);
print_signal_handler_and_exit();
return 2;
}

View File

@@ -0,0 +1,319 @@
// Copyright Antony Polukhin, 2016-2017.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/array.hpp>
BOOST_NOINLINE void foo(int i);
BOOST_NOINLINE void bar(int i);
BOOST_NOINLINE void bar(int i) {
boost::array<int, 5> a = {{-1, -231, -123, -23, -32}};
if (i >= 0) {
foo(a[i]);
} else {
std::terminate();
}
}
BOOST_NOINLINE void foo(int i) {
bar(--i);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//[getting_started_terminate_handlers
#include <signal.h> // ::signal, ::raise
#include <boost/stacktrace.hpp>
void my_signal_handler(int signum) {
::signal(signum, SIG_DFL);
boost::stacktrace::safe_dump_to("./backtrace.dump");
::raise(SIGABRT);
}
//]
void setup_handlers() {
//[getting_started_setup_handlers
::signal(SIGSEGV, &my_signal_handler);
::signal(SIGABRT, &my_signal_handler);
//]
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOST_CONSTEXPR_OR_CONST std::size_t shared_memory_size = 4096 * 8;
//[getting_started_terminate_handlers_shmem
#include <boost/stacktrace.hpp>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
boost::interprocess::shared_memory_object g_shm; // inited at program start
boost::interprocess::mapped_region g_region; // inited at program start
void my_signal_handler2(int signum) {
::signal(signum, SIG_DFL);
void** f = static_cast<void**>(g_region.get_address());
*f = reinterpret_cast<void*>(1); // Setting flag that shared memory now constains stacktrace.
boost::stacktrace::safe_dump_to(f + 1, g_region.get_size() - sizeof(void*));
::raise(SIGABRT);
}
//]
#include <iostream> // std::cerr
#include <fstream> // std::ifstream
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
inline void copy_and_run(const char* exec_name, char param, bool not_null) {
std::cout << "Running with param " << param << std::endl;
boost::filesystem::path command = exec_name;
command = command.parent_path() / (command.stem().string() + param + command.extension().string());
boost::filesystem::copy_file(exec_name, command, boost::filesystem::copy_option::overwrite_if_exists);
boost::filesystem::path command_args = command;
command_args += ' ';
command_args += param;
const int ret = std::system(command_args.string().c_str());
std::cout << "End Running with param " << param << "; ret code is " << ret << std::endl;
boost::system::error_code ignore;
boost::filesystem::remove(command, ignore);
if (not_null && !ret) {
std::exit(97);
} else if (!not_null && ret) {
std::exit(ret);
}
}
int run_1(const char* /*argv*/[]) {
setup_handlers();
foo(5);
return 11;
}
int run_2(const char* argv[]) {
if (!boost::filesystem::exists("./backtrace.dump")) {
if (std::string(argv[0]).find("noop") == std::string::npos) {
return 21;
}
boost::stacktrace::stacktrace st = boost::stacktrace::stacktrace::from_dump(std::cin);
if (st) {
return 22;
}
return 0;
}
//[getting_started_on_program_restart
if (boost::filesystem::exists("./backtrace.dump")) {
// there is a backtrace
std::ifstream ifs("./backtrace.dump");
boost::stacktrace::stacktrace st = boost::stacktrace::stacktrace::from_dump(ifs);
std::cout << "Previous run crashed:\n" << st << std::endl; /*<-*/
if (!st) {
return 23;
} /*->*/
// cleaning up
ifs.close();
boost::filesystem::remove("./backtrace.dump");
}
//]
return 0;
}
int run_3(const char* /*argv*/[]) {
using namespace boost::interprocess;
{
shared_memory_object shm_obj(open_or_create, "shared_memory", read_write);
shm_obj.swap(g_shm);
}
g_shm.truncate(shared_memory_size);
{
mapped_region m(g_shm, read_write, 0, shared_memory_size);
m.swap(g_region);
}
void** f = static_cast<void**>(g_region.get_address());
*f = 0;
::signal(SIGSEGV, &my_signal_handler2);
::signal(SIGABRT, &my_signal_handler2);
foo(5);
return 31;
}
int run_4(const char* argv[]) {
using namespace boost::interprocess;
{
shared_memory_object shm_obj(open_only, "shared_memory", read_write);
shm_obj.swap(g_shm);
}
{
mapped_region m(g_shm, read_write, 0, shared_memory_size);
m.swap(g_region);
}
//[getting_started_on_program_restart_shmem
void** f = static_cast<void**>(g_region.get_address());
if (*f) { // Checking if memory constains stacktrace.
boost::stacktrace::stacktrace st
= boost::stacktrace::stacktrace::from_dump(f + 1, g_region.get_size() - sizeof(bool));
std::cout << "Previous run crashed and left trace in shared memory:\n" << st << std::endl;
*f = 0; /*<-*/
shared_memory_object::remove("shared_memory");
if (std::string(argv[0]).find("noop") == std::string::npos) {
if (!st) {
return 43;
}
} else {
if (st) {
return 44;
}
}
} else {
return 42; /*->*/
}
//]
return 0;
}
#include <sstream>
int test_inplace() {
const bool is_noop = !boost::stacktrace::stacktrace();
{
// This is very dependent on compiler and link flags. No sane way to make it work, because:
// * BOOST_NOINLINE could be ignored by MSVC compiler if link-time optimization is enabled.
// * BOOST_FORCEINLINE could be ignored by GCC depending on the std::vector default constructor length.
const std::size_t frames_ss1 = boost::stacktrace::safe_dump_to("./backtrace2.dump");
boost::stacktrace::stacktrace ss2;
std::ifstream ifs("./backtrace2.dump");
boost::stacktrace::stacktrace ss1 = boost::stacktrace::stacktrace::from_dump(ifs);
ifs.close();
boost::filesystem::remove("./backtrace2.dump");
if (ss1.size() + 1 != frames_ss1 || ss2.size() != ss1.size()) {
std::cerr << "51: Stacktraces differ. Dumped size == " << frames_ss1 << ".\n" << ss1 << "\n vs \n" << ss2 << '\n';
} else if (ss1.size() > 1 && ss1[1].name() != ss2[1].name()) {
std::cerr << "52: Stacktraces differ:\n" << ss1 << "\n vs \n" << ss2 << '\n';
}
}
{
// This is very dependent on compiler and link flags. No sane way to make it work, because:
// * BOOST_NOINLINE could be ignored by MSVC compiler if link-time optimization is enabled.
// * BOOST_FORCEINLINE could be ignored by GCC depending on the std::vector default constructor length.
void* data[1024];
const std::size_t frames_ss1 = boost::stacktrace::safe_dump_to(data, sizeof(data));
boost::stacktrace::stacktrace ss2;
boost::stacktrace::stacktrace ss1 = boost::stacktrace::stacktrace::from_dump(data, sizeof(data));
if (ss1.size() + 1 != frames_ss1 || ss1.size() != ss2.size()) {
std::cerr << "53: Stacktraces differ. Dumped size == " << frames_ss1 << ".\n" << ss1 << "\n vs \n" << ss2 << '\n';
} else if (ss1.size() > 1 && ss1[1].name() != ss2[1].name()) {
std::cerr << "54: Stacktraces differ:\n" << ss1 << "\n vs \n" << ss2 << '\n';
}
}
{
void* data[1024];
boost::stacktrace::safe_dump_to(1024, data, sizeof(data));
if (boost::stacktrace::stacktrace::from_dump(data, sizeof(data))) {
std::cerr << "Stacktrace not empty!\n";
return 55;
}
}
{
void* data[1024];
boost::stacktrace::safe_dump_to(1, data, sizeof(data));
if (!is_noop && !boost::stacktrace::stacktrace::from_dump(data, sizeof(data))) {
std::cerr << "Stacktrace empty!\n";
return 56;
}
const std::size_t size_1_skipped = boost::stacktrace::stacktrace::from_dump(data, sizeof(data)).size();
boost::stacktrace::safe_dump_to(0, data, sizeof(data));
const std::size_t size_0_skipped = boost::stacktrace::stacktrace::from_dump(data, sizeof(data)).size();
if (!is_noop && (size_1_skipped + 1 != size_0_skipped)) {
std::cerr << "failed to skip 1 frame!\n";
return 57;
}
}
{
boost::stacktrace::safe_dump_to(0, 1, "./backtrace3.dump");
std::ifstream ifs("./backtrace3.dump");
boost::stacktrace::stacktrace ss1 = boost::stacktrace::stacktrace::from_dump(ifs);
ifs.close();
boost::stacktrace::safe_dump_to(1, 1, "./backtrace3.dump");
ifs.open("./backtrace3.dump");
boost::stacktrace::stacktrace ss2 = boost::stacktrace::stacktrace::from_dump(ifs);
ifs.close();
boost::filesystem::remove("./backtrace3.dump");
if (ss1.size() != ss2.size()) {
std::cerr << "Stacktraces differ:\n" << ss1 << "\n vs \n" << ss2 << '\n';
return 58;
}
if (!is_noop && ss1.size() != 1) {
std::cerr << "Stacktraces does not have size 1:\n" << ss1 << '\n';
return 59;
}
if (ss1 && ss1[0].address() == ss2[0].address()) {
std::cerr << "Stacktraces must differ:\n" << ss1 << "\n vs \n" << ss2 << '\n';
return 60;
}
}
return 0;
}
int main(int argc, const char* argv[]) {
if (argc < 2) {
// We are copying files to make sure that stacktrace printing works independently from executable name
copy_and_run(argv[0], '1', true);
copy_and_run(argv[0], '2', false);
#ifndef BOOST_WINDOWS
// There are some issues with async-safety of shared mmory writes on Windows.
copy_and_run(argv[0], '3', true);
copy_and_run(argv[0], '4', false);
#endif
return test_inplace();
}
switch (argv[1][0]) {
case '1': return run_1(argv);
case '2': return run_2(argv);
case '3': return run_3(argv);
case '4': return run_4(argv);
}
return 404;
}

View File

@@ -0,0 +1,78 @@
// Copyright Antony Polukhin, 2016-2017.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/config.hpp>
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//[getting_started_class_traced
#include <boost/stacktrace.hpp>
#include <boost/exception/all.hpp>
typedef boost::error_info<struct tag_stacktrace, boost::stacktrace::stacktrace> traced;
//]
//[getting_started_class_with_trace
template <class E>
void throw_with_trace(const E& e) {
throw boost::enable_error_info(e)
<< traced(boost::stacktrace::stacktrace());
}
//]
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOST_NOINLINE void oops(int i);
BOOST_NOINLINE void foo(int i);
BOOST_NOINLINE void bar(int i);
#include <stdexcept>
BOOST_NOINLINE void oops(int i) {
//[getting_started_throwing_with_trace
if (i >= 4)
throw_with_trace(std::out_of_range("'i' must be less than 4 in oops()"));
if (i <= 0)
throw_with_trace(std::logic_error("'i' must not be greater than zero in oops()"));
//]
foo(i);
std::exit(1);
}
#include <boost/array.hpp>
BOOST_NOINLINE void bar(int i) {
boost::array<int, 5> a = {{0, 0, 0, 0, 0}};
if (i < 5) {
if (i >= 0) {
foo(a[i]);
} else {
oops(i);
}
}
std::exit(2);
}
BOOST_NOINLINE void foo(int i) {
bar(--i);
}
#include <iostream>
int main() {
//[getting_started_catching_trace
try {
foo(5); // testing assert handler
} catch (const std::exception& e) {
std::cerr << e.what() << '\n';
const boost::stacktrace::stacktrace* st = boost::get_error_info<traced>(e);
if (st) {
std::cerr << *st << '\n'; /*<-*/ std::exit(0); /*->*/
} /*<-*/ std::exit(3); /*->*/
}
//]
return 5;
}

View File

@@ -0,0 +1,63 @@
// Copyright Antony Polukhin, 2016-2017.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/config.hpp>
#ifdef BOOST_NO_CXX11_RANGE_BASED_FOR
#include <boost/stacktrace.hpp>
#include <iostream> // std::cout
namespace bs = boost::stacktrace;
void dump_compact(const bs::stacktrace& st) {
for (unsigned i = 0; i < st.size(); ++i) {
bs::frame frame = st[i];
std::cout << frame.address() << ',';
}
std::cout << std::endl;
}
#else
//[getting_started_trace_addresses
#include <boost/stacktrace.hpp>
#include <iostream> // std::cout
namespace bs = boost::stacktrace;
void dump_compact(const bs::stacktrace& st) {
for (bs::frame frame: st) {
std::cout << frame.address() << ',';
}
std::cout << std::endl;
}
//]
#endif
BOOST_NOINLINE boost::stacktrace::stacktrace rec1(int i);
BOOST_NOINLINE boost::stacktrace::stacktrace rec2(int i);
BOOST_NOINLINE boost::stacktrace::stacktrace rec1(int i) {
if (i < 5) {
if (!i) return boost::stacktrace::stacktrace();
return rec2(--i);
}
return rec2(i - 2);
}
BOOST_NOINLINE boost::stacktrace::stacktrace rec2(int i) {
if (i < 5) {
if (!i) return boost::stacktrace::stacktrace();
return rec2(--i);
}
return rec2(i - 2);
}
int main() {
dump_compact(rec1(8));
}

View File

@@ -0,0 +1,38 @@
// Copyright Antony Polukhin, 2016-2017.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_USER_CONFIG <libs/stacktrace/example/user_config.hpp>
#include <boost/array.hpp>
#include <exception> // std::set_terminate, std::abort
#include <boost/stacktrace.hpp>
#include <iostream> // std::cerr
BOOST_NOINLINE void foo(int i);
BOOST_NOINLINE void bar(int i);
BOOST_NOINLINE void bar(int i) {
boost::array<int, 5> a = {{-1, -231, -123, -23, -32}};
if (i >= 0) {
foo(a[i]);
} else {
std::cerr << "Terminate called:\n" << boost::stacktrace::stacktrace() << '\n';
std::exit(0);
}
}
BOOST_NOINLINE void foo(int i) {
bar(--i);
}
int main() {
foo(5);
return 2;
}

View File

@@ -0,0 +1,55 @@
// Copyright Antony Polukhin, 2016-2017.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//[getting_started_user_config
#ifndef USER_CONFIG_HPP
#define USER_CONFIG_HPP
#include <boost/stacktrace/stacktrace_fwd.hpp>
#include <iosfwd>
namespace boost { namespace stacktrace {
template <class CharT, class TraitsT, class Allocator>
std::basic_ostream<CharT, TraitsT>& do_stream_st(std::basic_ostream<CharT, TraitsT>& os, const basic_stacktrace<Allocator>& bt);
template <class CharT, class TraitsT>
std::basic_ostream<CharT, TraitsT>& operator<<(std::basic_ostream<CharT, TraitsT>& os, const stacktrace& bt) {
return do_stream_st(os, bt);
}
}} // namespace boost::stacktrace
#endif // USER_CONFIG_HPP
//]
#ifndef USER_CONFIG2_HPP
#define USER_CONFIG2_HPP
//[getting_started_user_config_impl
namespace boost { namespace stacktrace {
template <class CharT, class TraitsT, class Allocator>
std::basic_ostream<CharT, TraitsT>& do_stream_st(std::basic_ostream<CharT, TraitsT>& os, const basic_stacktrace<Allocator>& bt) {
const std::streamsize w = os.width();
const std::size_t frames = bt.size();
for (std::size_t i = 0; i < frames; ++i) {
os.width(2);
os << i;
os.width(w);
os << "# ";
os << bt[i].name();
os << '\n';
}
return os;
}
}} // namespace boost::stacktrace
//]
#endif // USER_CONFIG2_HPP