refactor: use cpptrace

This commit is contained in:
Marcus Holland-Moritz 2024-10-17 13:27:40 +02:00
parent 2fcbee2a0b
commit fa644b4869
9 changed files with 136 additions and 74 deletions

View File

@ -154,8 +154,8 @@ if [[ "-$BUILD_TYPE-" == *-noperfmon-* ]]; then
CMAKE_ARGS="${CMAKE_ARGS} -DENABLE_PERFMON=0 -DWITH_MAN_OPTION=0"
fi
if [[ "-$BUILD_TYPE-" == *-nostacktrace-* ]]; then
CMAKE_ARGS="${CMAKE_ARGS} -DENABLE_STACKTRACE=0"
if [[ "-$BUILD_TYPE-" == *-stacktrace-* ]]; then
CMAKE_ARGS="${CMAKE_ARGS} -DENABLE_STACKTRACE=ON"
fi
if [[ "-$BUILD_TYPE-" == *-source-* ]]; then

View File

@ -13,11 +13,12 @@ CLANG_VERSION=18
FILE_VERSION=5.45
FILE_SHA512=12611a59ff766c22a55db4b4a9f80f95a0a2e916a1d8593612c6ead32c247102a8fdc23693c6bf81bda9b604d951a62c0051e91580b1b79e190a3504c0efc20a
BZIP2_VERSION=1.0.8
LIBARCHIVE_VERSION=3.7.4
LIBARCHIVE_VERSION=3.7.7
FLAC_VERSION=1.4.3
LIBUNWIND_VERSION=1.7.2
BENCHMARK_VERSION=1.8.5
OPENSSL_VERSION=3.0.14
BENCHMARK_VERSION=1.9.0
OPENSSL_VERSION=3.0.15
CPPTRACE_VERSION=0.7.2
RETRY=0
while true; do
@ -39,6 +40,7 @@ wget https://github.com/xiph/flac/releases/download/${FLAC_VERSION}/flac-${FLAC_
wget https://github.com/libunwind/libunwind/releases/download/v${LIBUNWIND_VERSION}/libunwind-${LIBUNWIND_VERSION}.tar.gz
wget https://github.com/google/benchmark/archive/refs/tags/v${BENCHMARK_VERSION}.tar.gz
wget https://github.com/openssl/openssl/releases/download/openssl-${OPENSSL_VERSION}/openssl-${OPENSSL_VERSION}.tar.gz
wget https://github.com/jeremy-rifkin/cpptrace/archive/refs/tags/v${CPPTRACE_VERSION}.tar.gz
for COMPILER in clang gcc; do
if [[ "$COMPILER" == "clang" ]]; then
@ -75,7 +77,7 @@ for COMPILER in clang gcc; do
cd openssl-${OPENSSL_VERSION}
./Configure --prefix="$INSTALL_DIR" --libdir=lib threads no-fips no-shared no-pic no-dso
make -j$(nproc)
make install
make install_sw
cd "$HOME/pkgs/$COMPILER"
tar xf ../libarchive-${LIBARCHIVE_VERSION}.tar.xz
@ -106,6 +108,15 @@ for COMPILER in clang gcc; do
cmake .. -DBENCHMARK_ENABLE_TESTING=OFF -DCMAKE_INSTALL_PREFIX="$INSTALL_DIR"
make -j$(nproc)
make install
cd "$HOME/pkgs/$COMPILER"
tar xf ../v${CPPTRACE_VERSION}.tar.gz
cd cpptrace-${CPPTRACE_VERSION}
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX="$INSTALL_DIR"
make -j$(nproc)
make install
done
cd "$HOME"

View File

@ -49,7 +49,7 @@ jobs:
- name: Configure Build
shell: cmd
run: |
cmake -B${{ runner.temp }}\build -S${{ runner.workspace }}\dwarfs -GNinja -DCMAKE_MAKE_PROGRAM=C:\bin\ninja.exe -DCMAKE_BUILD_TYPE=${{ matrix.build_mode }} -DWITH_UNIVERSAL_BINARY=ON -DWITH_TESTS=ON ${{ matrix.config.cmake_args }} -DCMAKE_TOOLCHAIN_FILE=C:\vcpkg\scripts\buildsystems\vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static -DVCPKG_INSTALLED_DIR=${{ runner.workspace }}\vcpkg-install-dwarfs -DDWARFS_ARTIFACTS_DIR=Z:\artifacts\dwarfs -DWITH_PXATTR=ON
cmake -B${{ runner.temp }}\build -S${{ runner.workspace }}\dwarfs -GNinja -DCMAKE_MAKE_PROGRAM=C:\bin\ninja.exe -DCMAKE_BUILD_TYPE=${{ matrix.build_mode }} -DWITH_UNIVERSAL_BINARY=ON -DWITH_TESTS=ON ${{ matrix.config.cmake_args }} -DCMAKE_TOOLCHAIN_FILE=C:\vcpkg\scripts\buildsystems\vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static -DVCPKG_INSTALLED_DIR=${{ runner.workspace }}\vcpkg-install-dwarfs -DDWARFS_ARTIFACTS_DIR=Z:\artifacts\dwarfs -DWITH_PXATTR=ON -DENABLE_STACKTRACE=${{ matrix.build_mode == 'Debug' && 'ON' || 'OFF' }}
- name: Run Build
shell: cmd
@ -186,9 +186,6 @@ jobs:
- arch: arm64v8
dist: ubuntu
build_type: gcc-debug-shared-noperfmon-ninja-split
- arch: amd64
dist: ubuntu
build_type: gcc-debug-shared-nostacktrace-ninja-split
- arch: arm64v8
dist: ubuntu
build_type: oldclang-debug-shared-make-split
@ -295,10 +292,10 @@ jobs:
build_type: gcc-release-ninja-O2-static
- arch: amd64
dist: ubuntu
build_type: clang-release-nostacktrace-ninja-static
build_type: clang-release-stacktrace-ninja-static
- arch: arm64v8
dist: ubuntu
build_type: clang-release-nostacktrace-ninja-static
build_type: clang-release-stacktrace-ninja-static
- arch: amd64
dist: ubuntu
build_type: clang-release-ninja-static
@ -313,16 +310,16 @@ jobs:
build_type: clang-release-ninja-O2-static
- arch: amd64
dist: ubuntu
build_type: clang-reldbg-ninja-static
build_type: clang-reldbg-stacktrace-ninja-static
- arch: arm64v8
dist: ubuntu
build_type: clang-reldbg-ninja-static
build_type: clang-reldbg-stacktrace-ninja-static
- arch: amd64
dist: ubuntu
build_type: clang-debug-ninja-static
build_type: clang-debug-stacktrace-ninja-static
- arch: arm64v8
dist: ubuntu
build_type: clang-debug-ninja-static
build_type: clang-debug-stacktrace-ninja-static
runs-on:
- self-hosted

View File

@ -39,9 +39,7 @@ option(ENABLE_RICEPP "build with RICEPP compression support" ON)
option(WITH_UNIVERSAL_BINARY "build with universal binary" OFF)
option(WITH_PXATTR "build with pxattr binary" OFF)
option(WITH_EXAMPLE "build with example binary" OFF)
if(NOT (APPLE OR WIN32))
option(ENABLE_STACKTRACE "build with symbolizer support" ON)
endif()
option(ENABLE_STACKTRACE "build with stack trace support" OFF)
if(APPLE)
option(USE_HOMEBREW_LIBARCHIVE "use libarchive from homebrew" ON)
endif()
@ -202,7 +200,7 @@ if(WITH_LIBDWARFS)
endif()
endif()
if(WIN32)
if(ENABLE_STACKTRACE)
find_package(cpptrace REQUIRED CONFIG)
endif()
@ -235,6 +233,7 @@ if(WITH_LIBDWARFS)
include(${CMAKE_SOURCE_DIR}/cmake/libdwarfs.cmake)
set(DWARFS_HAVE_CPPTRACE ${cpptrace_FOUND})
set(DWARFS_HAVE_LIBZSTD ON)
set(DWARFS_USE_JEMALLOC ${USE_JEMALLOC})
set(DWARFS_HAVE_RICEPP ${ENABLE_RICEPP})
@ -274,6 +273,9 @@ if(WITH_TOOLS)
list(APPEND BINARY_TARGETS ${tgt})
install(TARGETS ${tgt} RUNTIME DESTINATION bin)
if(WIN32)
install(FILES $<TARGET_PDB_FILE:${tgt}> DESTINATION bin OPTIONAL)
endif()
endforeach()
target_link_libraries(mkdwarfs_main PRIVATE dwarfs_reader dwarfs_writer dwarfs_rewrite)
@ -296,6 +298,9 @@ if(WITH_PXATTR)
add_executable(pxattr tools/src/pxattr.cpp)
list(APPEND BINARY_TARGETS pxattr)
install(TARGETS pxattr RUNTIME DESTINATION bin)
if(WIN32)
install(FILES $<TARGET_PDB_FILE:pxattr> DESTINATION bin OPTIONAL)
endif()
endif()
if(WITH_EXAMPLE)
@ -336,6 +341,7 @@ if(WITH_FUSE_DRIVER)
endif()
if(WINFSP)
install(TARGETS dwarfs-bin RUNTIME DESTINATION bin)
install(FILES $<TARGET_PDB_FILE:dwarfs-bin> DESTINATION bin OPTIONAL)
else()
add_custom_command(OUTPUT mount.dwarfs
COMMAND ${CMAKE_COMMAND} -E create_symlink dwarfs mount.dwarfs
@ -657,7 +663,6 @@ foreach(tgt ${LIBDWARFS_TARGETS} ${LIBDWARFS_OBJECT_TARGETS} dwarfs_test_helpers
if(WIN32)
target_link_libraries(${tgt} PRIVATE ntdll.lib dbghelp.lib)
target_link_libraries(${tgt} PRIVATE cpptrace::cpptrace)
endif()
endforeach()

View File

@ -29,6 +29,10 @@ pkg_check_modules(LIBARCHIVE REQUIRED IMPORTED_TARGET libarchive>=@LIBARCHIVE_RE
pkg_check_modules(XXHASH REQUIRED IMPORTED_TARGET libxxhash>=@XXHASH_REQUIRED_VERSION@)
pkg_check_modules(ZSTD REQUIRED IMPORTED_TARGET libzstd>=@ZSTD_REQUIRED_VERSION@)
if(@cpptrace_FOUND@) # cpptrace_FOUND
find_dependency(cpptrace CONFIG REQUIRED)
endif()
if(@LIBLZ4_FOUND@) # LIBLZ4_FOUND
pkg_check_modules(LIBLZ4 REQUIRED IMPORTED_TARGET liblz4>=@LIBLZ4_REQUIRED_VERSION@)
endif()

View File

@ -118,25 +118,6 @@ if(WIN32)
)
endif()
if(ENABLE_STACKTRACE)
target_sources(dwarfs_folly_lite PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/folly/folly/debugging/symbolizer/Dwarf.cpp
${CMAKE_CURRENT_SOURCE_DIR}/folly/folly/debugging/symbolizer/DwarfImpl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/folly/folly/debugging/symbolizer/DwarfLineNumberVM.cpp
${CMAKE_CURRENT_SOURCE_DIR}/folly/folly/debugging/symbolizer/DwarfSection.cpp
${CMAKE_CURRENT_SOURCE_DIR}/folly/folly/debugging/symbolizer/DwarfUtil.cpp
${CMAKE_CURRENT_SOURCE_DIR}/folly/folly/debugging/symbolizer/Elf.cpp
${CMAKE_CURRENT_SOURCE_DIR}/folly/folly/debugging/symbolizer/ElfCache.cpp
${CMAKE_CURRENT_SOURCE_DIR}/folly/folly/debugging/symbolizer/LineReader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/folly/folly/debugging/symbolizer/SignalHandler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/folly/folly/debugging/symbolizer/StackTrace.cpp
${CMAKE_CURRENT_SOURCE_DIR}/folly/folly/debugging/symbolizer/SymbolizePrinter.cpp
${CMAKE_CURRENT_SOURCE_DIR}/folly/folly/debugging/symbolizer/SymbolizedFrame.cpp
${CMAKE_CURRENT_SOURCE_DIR}/folly/folly/debugging/symbolizer/Symbolizer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/folly/folly/tracing/AsyncStack.cpp
)
endif()
set_property(TARGET dwarfs_folly_lite PROPERTY CXX_STANDARD 20)
target_include_directories(
dwarfs_folly_lite SYSTEM PUBLIC
@ -147,7 +128,7 @@ apply_folly_compile_options_to_target(dwarfs_folly_lite)
target_link_libraries(dwarfs_folly_lite PUBLIC folly_deps)
if(WITH_BENCHMARKS)
add_library(dwarfs_follybenchmark_lite OBJECT
add_library(dwarfs_follybenchmark_lite OBJECT
${CMAKE_CURRENT_SOURCE_DIR}/folly/folly/Benchmark.cpp
${CMAKE_CURRENT_SOURCE_DIR}/folly/folly/Format.cpp
${CMAKE_CURRENT_SOURCE_DIR}/folly/folly/Unicode.cpp
@ -192,13 +173,8 @@ if(WITH_BENCHMARKS)
target_link_libraries(dwarfs_follybenchmark_lite PUBLIC dwarfs_folly_lite)
endif()
if(ENABLE_STACKTRACE OR WITH_BENCHMARKS)
if(ENABLE_STACKTRACE)
set(_target dwarfs_folly_lite)
else()
set(_target dwarfs_follybenchmark_lite)
endif()
target_sources(${_target} PRIVATE
if(WITH_BENCHMARKS)
target_sources(dwarfs_follybenchmark_lite PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/folly/folly/SharedMutex.cpp
${CMAKE_CURRENT_SOURCE_DIR}/folly/folly/concurrency/CacheLocality.cpp
${CMAKE_CURRENT_SOURCE_DIR}/folly/folly/detail/Futex.cpp

View File

@ -201,6 +201,10 @@ if(LIBBROTLIDEC_FOUND AND LIBBROTLIENC_FOUND)
target_link_libraries(dwarfs_common PRIVATE PkgConfig::LIBBROTLIDEC PkgConfig::LIBBROTLIENC)
endif()
if(ENABLE_STACKTRACE)
target_link_libraries(dwarfs_common PRIVATE cpptrace::cpptrace)
endif()
target_link_libraries(dwarfs_extractor PRIVATE PkgConfig::LIBARCHIVE)
target_include_directories(dwarfs_common SYSTEM PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/fsst>)

View File

@ -32,11 +32,7 @@
#include <dwarfs/config.h>
#ifdef DWARFS_STACKTRACE_ENABLED
#include <folly/debugging/symbolizer/Symbolizer.h>
#if !(FOLLY_USE_SYMBOLIZER && FOLLY_HAVE_DWARF && FOLLY_HAVE_ELF)
#error "folly symbolizer is unavailable"
#endif
#include <cpptrace/cpptrace.hpp>
#endif
#include <fmt/chrono.h>
@ -207,15 +203,7 @@ void stream_logger::write(level_type level, const std::string& output,
std::vector<std::string_view> st_lines;
if (enable_stack_trace_ || level == FATAL) {
using namespace folly::symbolizer;
Symbolizer symbolizer(LocationInfoMode::FULL);
FrameArray<8> addresses;
getStackTraceSafe(addresses);
symbolizer.symbolize(addresses);
folly::symbolizer::StringSymbolizePrinter printer(
color_ ? folly::symbolizer::SymbolizePrinter::COLOR : 0);
printer.println(addresses, 3);
stacktrace = printer.str();
stacktrace = cpptrace::generate_trace().to_string(true);
split_to(stacktrace, '\n', st_lines);
if (st_lines.back().empty()) {
st_lines.pop_back();

View File

@ -26,6 +26,8 @@
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <mutex>
#include <optional>
#include <type_traits>
#if __has_include(<utf8cpp/utf8.h>)
@ -45,13 +47,12 @@
#include <dwarfs/config.h>
#ifdef _WIN32
#ifdef DWARFS_STACKTRACE_ENABLED
#include <cpptrace/cpptrace.hpp>
#include <signal.h>
#ifdef _WIN32
#include <tlhelp32.h>
#else
#ifdef DWARFS_STACKTRACE_ENABLED
#include <folly/debugging/symbolizer/SignalHandler.h>
#endif
#endif
@ -399,10 +400,28 @@ int get_current_umask() {
return mask;
}
#ifdef _WIN32
#ifdef DWARFS_STACKTRACE_ENABLED
namespace {
struct fatal_signal {
int signum;
std::string_view name;
};
constexpr std::array kFatalSignals{
fatal_signal{SIGSEGV, "SIGSEGV"}, fatal_signal{SIGILL, "SIGILL"},
fatal_signal{SIGFPE, "SIGFPE"}, fatal_signal{SIGABRT, "SIGABRT"},
fatal_signal{SIGTERM, "SIGTERM"},
#ifndef _WIN32
fatal_signal{SIGBUS, "SIGBUS"},
#endif
};
std::once_flag g_signal_handlers_installed;
#ifdef _WIN32
std::vector<HANDLE> suspend_other_threads() {
std::vector<HANDLE> handles;
DWORD currend_tid = ::GetCurrentThreadId();
@ -446,25 +465,83 @@ void resume_suspended_threads(const std::vector<HANDLE>& handles) {
}
}
void abort_handler(int signal) {
void fatal_signal_handler_win(int signal) {
auto suspended = suspend_other_threads();
std::cerr << "Caught signal " << signal << "\n";
std::optional<std::string> signame;
for (size_t i = 0; i < kFatalSignals.size(); ++i) {
if (signal == kFatalSignals[i].signum) {
signame = kFatalSignals[i].name;
break;
}
}
if (!signame) {
signame = std::to_string(signal);
}
std::cerr << "Caught signal " << *signame << "\n";
cpptrace::generate_trace().print();
resume_suspended_threads(suspended);
::exit(1);
}
#else
std::array<struct ::sigaction, kFatalSignals.size()> old_handlers;
void fatal_signal_handler_posix(int signal) {
std::optional<std::string> signame;
for (size_t i = 0; i < kFatalSignals.size(); ++i) {
if (signal == kFatalSignals[i].signum) {
::sigaction(signal, &old_handlers[i], nullptr);
signame = kFatalSignals[i].name;
break;
}
}
if (!signame) {
struct ::sigaction sa_dfl;
::memset(&sa_dfl, 0, sizeof(sa_dfl));
sa_dfl.sa_handler = SIG_DFL;
::sigaction(signal, &sa_dfl, nullptr);
signame = std::to_string(signal);
}
std::cerr << "Caught signal " << *signame << "\n";
cpptrace::generate_trace().print();
::raise(signal);
}
#endif
void install_signal_handlers_impl() {
for (size_t i = 0; i < kFatalSignals.size(); ++i) {
#ifdef _WIN32
::signal(kFatalSignals[i].signum, fatal_signal_handler_win);
#else
struct ::sigaction new_sa;
::memset(&new_sa, 0, sizeof(new_sa));
// this is potentially implemented as a macro
sigfillset(&new_sa.sa_mask);
new_sa.sa_handler = fatal_signal_handler_posix;
::sigaction(kFatalSignals[i].signum, &new_sa, &old_handlers[i]);
#endif
}
}
} // namespace
#endif
void install_signal_handlers() {
#ifdef _WIN32
::signal(SIGABRT, abort_handler);
#else
#ifdef DWARFS_STACKTRACE_ENABLED
folly::symbolizer::installFatalSignalHandler();
#endif
std::call_once(g_signal_handlers_installed, install_signal_handlers_impl);
#endif
}