Skip to content

Commit

Permalink
more tests and simpilifications
Browse files Browse the repository at this point in the history
  • Loading branch information
apolukhin committed Nov 25, 2023
1 parent 5df8c97 commit d4842f9
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 58 deletions.
12 changes: 10 additions & 2 deletions include/boost/stacktrace/current_exception.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,27 @@ namespace impl {
#if defined(__GNUC__) && defined(__ELF__)

BOOST_NOINLINE BOOST_SYMBOL_VISIBLE __attribute__((weak))
stacktrace current_exception_stacktrace() noexcept;
const char* current_exception_stacktrace() noexcept;

#endif

} // namespace impl


inline stacktrace current_exception_stacktrace() noexcept {
// Matches the constant from implementation
constexpr std::size_t kStacktraceDumpSize = 4096;

const char* trace = nullptr;
#if defined(__GNUC__) && defined(__ELF__)
if (impl::current_exception_stacktrace) {
return impl::current_exception_stacktrace();
trace = impl::current_exception_stacktrace();
}
#endif

if (trace) {
return stacktrace::from_dump(trace, kStacktraceDumpSize);
}
return stacktrace{0, 0};
}

Expand Down
72 changes: 25 additions & 47 deletions src/from_exception.cpp
Original file line number Diff line number Diff line change
@@ -1,24 +1,17 @@
// Copyright Antony Polukhin, 2023-2024.
// Copyright Andrei Nekrashevich, 2021.
//
// 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)

// Inspired by the coursework by Andrei Nekrashevich in the `libsfe`

#define BOOST_STACKTRACE_DYN_LINK
#define BOOST_STACKTRACE_LINK
#include <boost/stacktrace/safe_dump_to.hpp>
#include <boost/stacktrace/stacktrace.hpp>

#include <boost/assert.hpp>

#include <cstddef>
#include <exception>
#include <mutex>
#include <unordered_map>
#include <vector>
#include <utility>

#include <dlfcn.h>
Expand All @@ -27,8 +20,19 @@ namespace {

constexpr std::size_t kStacktraceDumpSize = 4096;

inline void* get_current_exception_raw_ptr() noexcept {
// https://github.com/gcc-mirror/gcc/blob/16e2427f50c208dfe07d07f18009969502c25dc8/libstdc%2B%2B-v3/libsupc%2B%2B/eh_ptr.cc#L147
auto exc_ptr = std::current_exception();
return *static_cast<void**>(static_cast<void*>(&exc_ptr));
}

} // namespace

// Inspired by the coursework by Andrei Nekrashevich in the `libsfe`
namespace {

std::mutex mutex;
std::unordered_map<void*, const char*> exception_to_dump;
std::unordered_map<void*, const char*> exception_to_dump_mapping;

struct decrement_on_destroy {
std::size_t& to_decrement;
Expand Down Expand Up @@ -66,7 +70,7 @@ void* __cxa_allocate_exception(size_t thrown_size) throw() {

{
const std::lock_guard<std::mutex> guard{mutex};
exception_to_dump[ptr] = dump_ptr;
exception_to_dump_mapping[ptr] = dump_ptr;
}

return ptr;
Expand All @@ -91,7 +95,7 @@ void __cxa_free_exception(void* thrown_object) throw() {

{
const std::lock_guard<std::mutex> guard{mutex};
exception_to_dump.erase(thrown_object);
exception_to_dump_mapping.erase(thrown_object);
}

orig_free_exception(thrown_object);
Expand Down Expand Up @@ -121,7 +125,7 @@ void __cxa_decrement_exception_refcount(void *thrown_object) throw() {
);
if (exception_header->referenceCount == 1) {
const std::lock_guard<std::mutex> guard{mutex};
exception_to_dump.erase(thrown_object);
exception_to_dump_mapping.erase(thrown_object);
}

orig_decrement_refcount(thrown_object);
Expand All @@ -131,50 +135,24 @@ void __cxa_decrement_exception_refcount(void *thrown_object) throw() {

namespace boost { namespace stacktrace { namespace impl {

namespace {

inline void* get_current_exception_raw_ptr() noexcept {
// https://github.com/gcc-mirror/gcc/blob/16e2427f50c208dfe07d07f18009969502c25dc8/libstdc%2B%2B-v3/libsupc%2B%2B/eh_ptr.cc#L147
auto exc_ptr = std::current_exception();
return *static_cast<void**>(static_cast<void*>(&exc_ptr));
}

} // namespace

BOOST_SYMBOL_EXPORT stacktrace current_exception_stacktrace() noexcept {
void* exc_raw_ptr = get_current_exception_raw_ptr();
BOOST_SYMBOL_EXPORT const char* current_exception_stacktrace() noexcept {
void* const exc_raw_ptr = get_current_exception_raw_ptr();
if (!exc_raw_ptr) {
return stacktrace{0, 0};
return nullptr;
}

const char* stacktrace_dump_ptr = nullptr;
{
const std::lock_guard<std::mutex> guard{mutex};
auto it = exception_to_dump.find(exc_raw_ptr);
if (it != exception_to_dump.end()) {
stacktrace_dump_ptr = it->second;
}
}

if (!stacktrace_dump_ptr) {
return stacktrace{0, 0};
const std::lock_guard<std::mutex> guard{mutex};
const auto it = exception_to_dump_mapping.find(exc_raw_ptr);
if (it != exception_to_dump_mapping.end()) {
return it->second;
}

return stacktrace::from_dump(stacktrace_dump_ptr, kStacktraceDumpSize);
return nullptr;
}

BOOST_SYMBOL_EXPORT std::vector<stacktrace> pending_traces() {
std::vector<stacktrace> result;

BOOST_SYMBOL_EXPORT void assert_no_pending_traces() noexcept {
const std::lock_guard<std::mutex> guard{mutex};
result.reserve(exception_to_dump.size());
for (const auto& pair : exception_to_dump) {
result.push_back(
stacktrace::from_dump(pair.second, kStacktraceDumpSize)
);
}

return result;
BOOST_ASSERT(exception_to_dump_mapping.empty());
}

}}} // namespace boost::stacktrace::impl
Expand Down
5 changes: 2 additions & 3 deletions test/Jamfile.v2
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,8 @@ test-suite stacktrace_tests
[ run test_from_exception.cpp : : : <library>/boost/stacktrace//boost_stacktrace_from_exception $(LINKSHARED_BASIC) <debug-symbols>on : from_exception_basic ]
[ run test_from_exception.cpp : : : <library>/boost/stacktrace//boost_stacktrace_from_exception $(LINKSHARED_BT) <debug-symbols>on : from_exception_bt ]

# Link errors, no `collect`:
#[ run test_from_exception.cpp : : : <library>/boost/stacktrace//boost_stacktrace_from_exception $(FORCE_SYMBOL_EXPORT) $(BASIC_DEPS) <debug-symbols>on : from_exception_basic_ho ]
#[ run test_from_exception.cpp : : : <library>/boost/stacktrace//boost_stacktrace_from_exception <define>BOOST_STACKTRACE_USE_BACKTRACE $(BT_DEPS) <debug-symbols>on : from_exception_bt_ho ]
[ run test_from_exception.cpp : : : <library>/boost/stacktrace//boost_stacktrace_from_exception $(FORCE_SYMBOL_EXPORT) $(BASIC_DEPS) <debug-symbols>on : from_exception_basic_ho ]
[ run test_from_exception.cpp : : : <library>/boost/stacktrace//boost_stacktrace_from_exception <define>BOOST_STACKTRACE_USE_BACKTRACE $(BT_DEPS) <debug-symbols>on : from_exception_bt_ho ]
;

# Assuring that examples compile and run. Adding sources from `examples` directory to the `type_index` test suite.
Expand Down
9 changes: 3 additions & 6 deletions test/test_from_exception.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,21 @@

#include <boost/stacktrace.hpp>

#include <iostream>
#include <thread>

#include <boost/core/lightweight_test.hpp>

namespace boost { namespace stacktrace { namespace impl {
std::vector<stacktrace> pending_traces();
void assert_no_pending_traces() noexcept;
}}}

using boost::stacktrace::current_exception_stacktrace;
using boost::stacktrace::stacktrace;

struct test_no_pending_on_finish {
~test_no_pending_on_finish() {
const auto pending = boost::stacktrace::impl::pending_traces();
for (const auto& trace: pending) {
std::cerr << "!!!! Pending trace :\n" << trace << '\n';
}
BOOST_TEST(pending.empty());
boost::stacktrace::impl::assert_no_pending_traces();
}
};

Expand Down

0 comments on commit d4842f9

Please sign in to comment.