diff options
Diffstat (limited to 'library/cpp/dwarf_backtrace/backtrace.cpp')
-rw-r--r-- | library/cpp/dwarf_backtrace/backtrace.cpp | 67 |
1 files changed, 44 insertions, 23 deletions
diff --git a/library/cpp/dwarf_backtrace/backtrace.cpp b/library/cpp/dwarf_backtrace/backtrace.cpp index a955d07249..7dcfd12ea7 100644 --- a/library/cpp/dwarf_backtrace/backtrace.cpp +++ b/library/cpp/dwarf_backtrace/backtrace.cpp @@ -6,6 +6,8 @@ #include <util/system/type_name.h> #include <util/system/execpath.h> +#include <mutex> + namespace NDwarf { namespace { struct TContext { @@ -31,32 +33,51 @@ namespace NDwarf { }; return static_cast<int>(context->Callback(lineInfo)); } - } - TMaybe<TError> ResolveBacktrace(TArrayRef<const void* const> backtrace, TCallback callback) { - TContext context{.Callback = callback}; - // Intentionally never freed (see https://a.yandex-team.ru/arc/trunk/arcadia/contrib/libs/backtrace/backtrace.h?rev=6789902#L80). - static auto* state = backtrace_create_state( - GetPersistentExecPath().c_str(), - 1 /* threaded */, - HandleLibBacktraceError, - &context /* data for the error callback */ - ); - if (nullptr == state) { - static const auto initError = context.Error; - return initError; - } - for (const void* address : backtrace) { - int status = backtrace_pcinfo( - state, - reinterpret_cast<uintptr_t>(address) - 1, // last byte of the call instruction - HandleLibBacktraceFrame, + auto CreateBacktraceState(TContext& context, bool threaded) { + return backtrace_create_state( + GetPersistentExecPath().c_str(), + static_cast<int>(threaded), HandleLibBacktraceError, - &context /* data for both callbacks */); - if (0 != status) { - break; + &context /* data for the error callback */ + ); + } + + TMaybe<TError> ResolveBacktraceImpl(backtrace_state* state, TArrayRef<const void* const> backtrace, TContext& context) { + if (nullptr == state) { + static const auto initError = context.Error; + return initError; } + for (const void* address : backtrace) { + int status = backtrace_pcinfo( + state, + reinterpret_cast<uintptr_t>(address) - 1, // last byte of the call instruction + HandleLibBacktraceFrame, + HandleLibBacktraceError, + &context /* data for both callbacks */); + if (0 != status) { + break; + } + } + return context.Error; } - return context.Error; + } + + TMaybe<TError> ResolveBacktrace(TArrayRef<const void* const> backtrace, TCallback callback) { + TContext context{.Callback = callback}; + // Intentionally never freed (see the documentation to `backtrace_create_state`). + static auto* state{CreateBacktraceState(context, true /* enable threading support */)}; + + return ResolveBacktraceImpl(state, backtrace, context); + } + + TMaybe<TError> ResolveBacktraceLocked(TArrayRef<const void* const> backtrace, TCallback callback) { + TContext context{.Callback = callback}; + // Intentionally never freed (see the documentation to `backtrace_create_state`). + static auto* state{CreateBacktraceState(context, false /* disable threading support */)}; + static std::mutex mutex; + + const std::lock_guard lock{mutex}; + return ResolveBacktraceImpl(state, backtrace, context); } } |