mirror of
https://github.com/hanzoai/datastore.git
synced 2026-09-26 13:55:07 +00:00
jemalloc: use a safe prof_backtrace hook (system backtrace) on macOS instead of the crashing default
This commit is contained in:
@@ -203,10 +203,9 @@ target_compile_options(_jemalloc PRIVATE ${WITHOUT_COVERAGE_FLAGS_LIST})
|
||||
|
||||
target_compile_definitions(_jemalloc PRIVATE -DJEMALLOC_PROF=1)
|
||||
|
||||
# jemalloc provides several unwind flavors for the profiler backtrace:
|
||||
# jemalloc provides support two unwind flavors:
|
||||
# - JEMALLOC_PROF_LIBUNWIND - unw_backtrace() - gnu libunwind (compatible with llvm libunwind)
|
||||
# - JEMALLOC_PROF_LIBGCC - _Unwind_Backtrace() - the original HP libunwind and the one coming with gcc / g++ / libstdc++.
|
||||
# - JEMALLOC_PROF_GCC - __builtin_return_address() - a plain frame-pointer walk, no DWARF/unwinder.
|
||||
#
|
||||
# But for JEMALLOC_PROF_LIBGCC it also calls _Unwind_Backtrace() during
|
||||
# bootstraping of jemalloc, which may lead to deadlock, if the dlsym will do
|
||||
@@ -216,16 +215,8 @@ target_compile_definitions(_jemalloc PRIVATE -DJEMALLOC_PROF=1)
|
||||
#
|
||||
# And since ClickHouse unwind already supports unw_backtrace() we can safely
|
||||
# switch to it to avoid this deadlock.
|
||||
if (OS_DARWIN)
|
||||
# On macOS the profiler samples inside the malloc hook and unwinds the current stack, which on
|
||||
# arm64 includes frame-pointer-less libsystem frames (e.g. the malloc-zone shims). llvm libunwind's
|
||||
# DWARF stepper null-derefs on those, crashing the server. Use the frame-pointer backtrace instead
|
||||
# (ClickHouse builds with -fno-omit-frame-pointer); it needs no unwinder and cannot fault that way.
|
||||
target_compile_definitions (_jemalloc PRIVATE -DJEMALLOC_PROF_GCC=1)
|
||||
else ()
|
||||
target_compile_definitions (_jemalloc PRIVATE -DJEMALLOC_PROF_LIBUNWIND=1)
|
||||
target_link_libraries (_jemalloc PRIVATE unwind)
|
||||
endif ()
|
||||
target_compile_definitions (_jemalloc PRIVATE -DJEMALLOC_PROF_LIBUNWIND=1)
|
||||
target_link_libraries (_jemalloc PRIVATE unwind)
|
||||
|
||||
# for RTLD_NEXT
|
||||
target_compile_options(_jemalloc PRIVATE -D_GNU_SOURCE)
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
# include <Common/TraceSender.h>
|
||||
# include <Common/logger_useful.h>
|
||||
|
||||
# if defined(OS_DARWIN)
|
||||
# include <execinfo.h>
|
||||
# endif
|
||||
|
||||
# define STRINGIFY_HELPER(x) #x
|
||||
# define STRINGIFY(x) STRINGIFY_HELPER(x)
|
||||
|
||||
@@ -176,6 +180,18 @@ void setLastFlushProfile(const char * filename)
|
||||
last_flush_profile = std::string_view{last_flush_profile_buffer.data(), last_flush_profile_size};
|
||||
}
|
||||
|
||||
#if defined(OS_DARWIN)
|
||||
/// jemalloc's built-in profiler backtraces crash inside the malloc hook on macOS: the libunwind DWARF
|
||||
/// stepper null-derefs, and the __builtin_frame_address walk faults on frames without a set-up frame
|
||||
/// pointer. The system backtrace() validates the frame-pointer chain (and does not allocate), so it is
|
||||
/// safe to call here and is what we use for the profiler elsewhere. Installed via the prof_backtrace hook.
|
||||
void jemallocProfBacktrace(void ** vec, unsigned * len, unsigned max_len)
|
||||
{
|
||||
int size = ::backtrace(vec, static_cast<int>(max_len));
|
||||
*len = size > 0 ? static_cast<unsigned>(size) : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void setCollectLocalProfileSamplesInTraceLog(bool value)
|
||||
@@ -208,6 +224,10 @@ void setup(
|
||||
setValue("experimental.hooks.prof_sample", &jemallocAllocationTracker);
|
||||
setValue("experimental.hooks.prof_sample_free", &jemallocDeallocationTracker);
|
||||
setValue("experimental.hooks.prof_dump", &setLastFlushProfile);
|
||||
#if defined(OS_DARWIN)
|
||||
/// Replace jemalloc's default (crash-prone on macOS) profiler backtrace with the safe system one.
|
||||
setValue("experimental.hooks.prof_backtrace", &jemallocProfBacktrace);
|
||||
#endif
|
||||
}
|
||||
|
||||
void verifySetup(
|
||||
|
||||
Reference in New Issue
Block a user