mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-19 16:20:50 +00:00
Fix stacktraces on MacOS (#59690)
This commit is contained in:
parent
b06e13fc57
commit
50828dade2
@ -254,10 +254,17 @@ endif()
|
||||
|
||||
include(cmake/cpu_features.cmake)
|
||||
|
||||
# Asynchronous unwind tables are needed for Query Profiler.
|
||||
# They are already by default on some platforms but possibly not on all platforms.
|
||||
# Enable it explicitly.
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} -fasynchronous-unwind-tables")
|
||||
|
||||
# Query Profiler doesn't work on MacOS for several reasons
|
||||
# - PHDR cache is not available
|
||||
# - We use native functionality to get stacktraces which is not async signal safe
|
||||
# and thus we don't need to generate asynchronous unwind tables
|
||||
if (NOT OS_DARWIN)
|
||||
# Asynchronous unwind tables are needed for Query Profiler.
|
||||
# They are already by default on some platforms but possibly not on all platforms.
|
||||
# Enable it explicitly.
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} -fasynchronous-unwind-tables")
|
||||
endif()
|
||||
|
||||
# Reproducible builds.
|
||||
if (CMAKE_BUILD_TYPE_UC STREQUAL "DEBUG")
|
||||
|
@ -1,6 +1,10 @@
|
||||
#include <libunwind.h>
|
||||
|
||||
/// On MacOS this function will be replaced with a dynamic symbol
|
||||
/// from the system library.
|
||||
#if !defined(OS_DARWIN)
|
||||
int backtrace(void ** buffer, int size)
|
||||
{
|
||||
return unw_backtrace(buffer, size);
|
||||
}
|
||||
#endif
|
||||
|
2
contrib/llvm-project
vendored
2
contrib/llvm-project
vendored
@ -1 +1 @@
|
||||
Subproject commit 2568a7cd1297c7c3044b0f3cc0c23a6f6444d856
|
||||
Subproject commit d2142eed98046a47ff7112e3cc1e197c8a5cd80f
|
@ -4,6 +4,7 @@
|
||||
#include <base/constexpr_helpers.h>
|
||||
#include <base/demangle.h>
|
||||
|
||||
#include <Common/scope_guard_safe.h>
|
||||
#include <Common/Dwarf.h>
|
||||
#include <Common/Elf.h>
|
||||
#include <Common/MemorySanitizer.h>
|
||||
@ -24,6 +25,15 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
|
||||
#if defined(OS_DARWIN)
|
||||
/// This header contains functions like `backtrace` and `backtrace_symbols`
|
||||
/// Which will be used for stack unwinding on Mac.
|
||||
/// Read: https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/backtrace.3.html
|
||||
#include "execinfo.h"
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
/// Currently this variable is set up once on server startup.
|
||||
@ -262,6 +272,33 @@ void StackTrace::forEachFrame(
|
||||
callback(current_inline_frame);
|
||||
}
|
||||
|
||||
callback(current_frame);
|
||||
}
|
||||
#elif defined(OS_DARWIN)
|
||||
UNUSED(fatal);
|
||||
|
||||
/// This function returns an array of string in a special (a little bit weird format)
|
||||
/// The frame number, library name, address in hex, mangled symbol name, `+` sign, the offset.
|
||||
char** strs = ::backtrace_symbols(frame_pointers.data(), static_cast<int>(size));
|
||||
SCOPE_EXIT_SAFE({free(strs);});
|
||||
|
||||
for (size_t i = offset; i < size; ++i)
|
||||
{
|
||||
StackTrace::Frame current_frame;
|
||||
|
||||
std::vector<std::string> split;
|
||||
boost::split(split, strs[i], isWhitespaceASCII);
|
||||
split.erase(
|
||||
std::remove_if(
|
||||
split.begin(), split.end(),
|
||||
[](const std::string & x) { return x.empty(); }),
|
||||
split.end());
|
||||
assert(split.size() == 6);
|
||||
|
||||
current_frame.virtual_addr = frame_pointers[i];
|
||||
current_frame.physical_addr = frame_pointers[i];
|
||||
current_frame.object = split[1];
|
||||
current_frame.symbol = split[3];
|
||||
callback(current_frame);
|
||||
}
|
||||
#else
|
||||
@ -306,7 +343,11 @@ StackTrace::StackTrace(const ucontext_t & signal_context)
|
||||
|
||||
void StackTrace::tryCapture()
|
||||
{
|
||||
#if defined(OS_DARWIN)
|
||||
size = backtrace(frame_pointers.data(), capacity);
|
||||
#else
|
||||
size = unw_backtrace(frame_pointers.data(), capacity);
|
||||
#endif
|
||||
__msan_unpoison(frame_pointers.data(), size * sizeof(frame_pointers[0]));
|
||||
}
|
||||
|
||||
@ -376,7 +417,7 @@ toStringEveryLineImpl([[maybe_unused]] bool fatal, const StackTraceRefTriple & s
|
||||
return callback("<Empty trace>");
|
||||
|
||||
size_t frame_index = stack_trace.offset;
|
||||
#if defined(__ELF__) && !defined(OS_FREEBSD)
|
||||
#if (defined(__ELF__) && !defined(OS_FREEBSD)) || defined(OS_DARWIN)
|
||||
size_t inline_frame_index = 0;
|
||||
auto callback_wrapper = [&](const StackTrace::Frame & frame)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user