aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/dwarf_backtrace/backtrace.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'library/cpp/dwarf_backtrace/backtrace.cpp')
-rw-r--r--library/cpp/dwarf_backtrace/backtrace.cpp67
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);
}
}