mirror of
https://github.com/boostorg/stacktrace.git
synced 2026-01-19 16:52:10 +00:00
fix memory consumption when using libbacktrace and speedup trace decoding
This commit is contained in:
@@ -60,30 +60,54 @@ inline void libbacktrace_error_callback(void* /*data*/, const char* /*msg*/, int
|
||||
// Do nothing, just return.
|
||||
}
|
||||
|
||||
|
||||
inline ::backtrace_state* construct_state(const program_location& prog_location) BOOST_NOEXCEPT {
|
||||
// Currently `backtrace_create_state` can not detect file name on Windows https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82543
|
||||
// That's why we provide a `prog_location` here.
|
||||
return ::backtrace_create_state(
|
||||
prog_location.name(), 0 /*thread-safe*/, boost::stacktrace::detail::libbacktrace_error_callback, 0
|
||||
);
|
||||
|
||||
// TODO: this does not seem to work well when this function is in .so:
|
||||
// Not async-signal-safe, so this method is not called from async-safe functions.
|
||||
//
|
||||
// This function is not async signal safe because:
|
||||
// * Dynamic initialization of a block-scope variable with static storage duration could lock a mutex
|
||||
// * No guarantees on `backtrace_create_state` function.
|
||||
|
||||
// Not async-signal-safe, so this method is not called from async-safe functions.
|
||||
//
|
||||
// This function is not async signal safe because:
|
||||
// * Dynamic initialization of a block-scope variable with static storage duration could lock a mutex
|
||||
// * No guarantees on `backtrace_create_state` function.
|
||||
//
|
||||
// Currently `backtrace_create_state` can not detect file name on Windows https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82543
|
||||
// That's why we provide a `prog_location` here.
|
||||
BOOST_SYMBOL_VISIBLE inline ::backtrace_state* construct_state(const program_location& prog_location) BOOST_NOEXCEPT {
|
||||
// [dcl.inline]: A static local variable in an inline function with external linkage always refers to the same object.
|
||||
|
||||
/*
|
||||
static ::backtrace_state* state = ::backtrace_create_state(
|
||||
0, 1 , boost::stacktrace::detail::libbacktrace_error_callback, 0
|
||||
);
|
||||
// TODO: The most obvious solution:
|
||||
//
|
||||
//static ::backtrace_state* state = ::backtrace_create_state(
|
||||
// prog_location.name(),
|
||||
// 1, // allow safe concurrent usage of the same state
|
||||
// boost::stacktrace::detail::libbacktrace_error_callback,
|
||||
// 0 // pointer to data that will be passed to callback
|
||||
//);
|
||||
//
|
||||
//
|
||||
// Unfortunately, that solution segfaults when `construct_state()` function is in .so file
|
||||
// and multiple threads concurrently work with state.
|
||||
|
||||
|
||||
#ifndef BOOST_HAS_THREADS
|
||||
static
|
||||
#else
|
||||
|
||||
// Result of `construct_state()` invocation is not stored by the callers, so `thread_local`
|
||||
// gives a single `state` per thread and that state is not shared between threads in any way.
|
||||
|
||||
# ifndef BOOST_NO_CXX11_THREAD_LOCAL
|
||||
thread_local
|
||||
# elif defined(__GNUC__)
|
||||
static __thread
|
||||
# else
|
||||
/* just a local variable */
|
||||
# endif
|
||||
|
||||
#endif
|
||||
::backtrace_state* state = ::backtrace_create_state(
|
||||
prog_location.name(),
|
||||
0,
|
||||
boost::stacktrace::detail::libbacktrace_error_callback,
|
||||
0
|
||||
);
|
||||
return state;
|
||||
*/
|
||||
}
|
||||
|
||||
struct to_string_using_backtrace {
|
||||
|
||||
@@ -220,14 +220,14 @@ for local p in [ glob ../example/*.cpp ]
|
||||
test-suite stacktrace_torture
|
||||
:
|
||||
[ run torture.cpp test_impl.cpp : : : <debug-symbols>on <define>BOOST_STACKTRACE_USE_BACKTRACE $(BT_DEPS) : torture_backtrace_ho ]
|
||||
[ run torture.cpp test_impl.cpp : : : <debug-symbols>on <define>BOOST_STACKTRACE_USE_ADDR2LINE $(AD2L_DEPS) : torture_addr2line_ho ]
|
||||
#[ run torture.cpp test_impl.cpp : : : <debug-symbols>on <define>BOOST_STACKTRACE_USE_ADDR2LINE $(AD2L_DEPS) : torture_addr2line_ho ]
|
||||
[ run torture.cpp test_impl.cpp : : : <debug-symbols>on $(WIND_DEPS) : torture_windbg_ho ]
|
||||
[ run torture.cpp test_impl.cpp : : : <debug-symbols>on <define>BOOST_STACKTRACE_USE_WINDBG_CACHED $(WICA_DEPS) : torture_windbg_cached_ho ]
|
||||
[ run torture.cpp test_impl.cpp : : : <debug-symbols>on $(FORCE_SYMBOL_EXPORT) $(BASIC_DEPS) : torture_basic_ho ]
|
||||
[ run torture.cpp test_impl.cpp : : : <debug-symbols>on <define>BOOST_STACKTRACE_TEST_NO_DEBUG_AT_ALL $(BASIC_DEPS) : torture_basic_ho_empty ]
|
||||
|
||||
[ run torture.cpp test_impl.cpp : : : <debug-symbols>on <library>.//test_impl_lib_backtrace $(LINKSHARED_BT) : torture_backtrace_lib ]
|
||||
[ run torture.cpp test_impl.cpp : : : <debug-symbols>on <library>.//test_impl_lib_addr2line $(LINKSHARED_AD2L) : torture_addr2line_lib ]
|
||||
#[ run torture.cpp test_impl.cpp : : : <debug-symbols>on <library>.//test_impl_lib_addr2line $(LINKSHARED_AD2L) : torture_addr2line_lib ]
|
||||
[ run torture.cpp test_impl.cpp : : : <debug-symbols>on <library>.//test_impl_lib_windbg $(LINKSHARED_WIND) : torture_windbg_lib ]
|
||||
[ run torture.cpp test_impl.cpp : : : <debug-symbols>on <library>.//test_impl_lib_windbg_cached $(LINKSHARED_WIND_CACHED) : torture_windbg_cached_lib ]
|
||||
[ run torture.cpp test_impl.cpp : : : <debug-symbols>on <library>.//test_impl_lib_basic $(LINKSHARED_BASIC) : torture_basic_lib ]
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
int main() {
|
||||
int result = 0;
|
||||
for (unsigned i = 0; i < 10000; ++i) {
|
||||
for (unsigned i = 0; i < 10000000; ++i) {
|
||||
result += make_some_stacktrace1()[0].source_line();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user