diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 85a61bc..4a6f380 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -266,10 +266,21 @@ jobs: - name: Use the installed library run: | cd ../boost-root/libs/$LIBRARY/test/cmake_install_test && mkdir __build__ && cd __build__ - cmake -DCMAKE_INSTALL_PREFIX=~/.local .. - cmake --build . + export LD_LIBRARY_PATH=$HOME/.local/lib:$LD_LIBRARY_PATH - ctest --output-on-failure --no-tests=error + + set -e + if [[ "$OSTYPE" == "darwin"* ]]; then + BACKENDS_ARRAY=(stacktrace stacktrace_noop stacktrace_basic) + else + BACKENDS_ARRAY=(stacktrace stacktrace_noop stacktrace_basic stacktrace_backtrace) + fi + for BACKEND in ${BACKENDS_ARRAY[@]}; do + rm -rf * + cmake -DCMAKE_INSTALL_PREFIX=~/.local -DBOOST_STACKTRACE_IMPL_BACKEND=${BACKEND} .. + cmake --build . + ctest --output-on-failure --no-tests=error -V + done posix-cmake-test: strategy: @@ -426,10 +437,20 @@ jobs: shell: cmd run: | cd ../boost-root/libs/%LIBRARY%/test/cmake_install_test && mkdir __build__ && cd __build__ - cmake -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix .. + cmake -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix -DBOOST_STACKTRACE_IMPL_BACKEND=stacktrace .. cmake --build . --config Debug PATH C:\cmake-prefix\bin;%PATH% - ctest --output-on-failure --no-tests=error -C Debug + ctest --output-on-failure --no-tests=error -C Debug -V + + cmake -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix -DBOOST_STACKTRACE_IMPL_BACKEND=stacktrace_windbg .. + cmake --build . --config Debug + PATH C:\cmake-prefix\bin;%PATH% + ctest --output-on-failure --no-tests=error -C Debug -V + + cmake -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix -DBOOST_STACKTRACE_IMPL_BACKEND=stacktrace_windbg_cached .. + cmake --build . --config Debug + PATH C:\cmake-prefix\bin;%PATH% + ctest --output-on-failure --no-tests=error -C Debug -V - name: Use the installed library (RelWithDebInfo) shell: cmd diff --git a/CMakeLists.txt b/CMakeLists.txt index a4bde74..771f6f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ # Distributed under the Boost Software License, Version 1.0. # https://www.boost.org/LICENSE_1_0.txt -cmake_minimum_required(VERSION 3.5...3.16) +cmake_minimum_required(VERSION 3.8...4.20) project(boost_stacktrace VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) @@ -72,7 +72,7 @@ stacktrace_check(BOOST_STACKTRACE_HAS_WINDBG has_windbg.cpp "" "dbgeng;ole32" "" stacktrace_check(BOOST_STACKTRACE_HAS_WINDBG_CACHED has_windbg_cached.cpp "${CMAKE_CURRENT_SOURCE_DIR}/../config/include" "dbgeng;ole32" "") set(_default_from_exception ON) -if (NOT CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64|amd64|i386|i686|x86" OR CMAKE_CXX_PLATFORM_ID MATCHES "Cygwin") +if (CMAKE_CXX_PLATFORM_ID MATCHES "Cygwin") set(_default_from_exception OFF) endif() @@ -142,8 +142,6 @@ stacktrace_add_library(from_exception ${BOOST_STACKTRACE_ENABLE_FROM_EXCEPTION} # -if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") - +if(BUILD_TESTING) add_subdirectory(test) - endif() diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index a7e4615..0af76b9 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -249,8 +249,7 @@ rule build-stacktrace-from-exception ( props * ) case "off" : return no ; } - local arch = [ property.select : $(props) ] ; - if ( $(arch) && ( $(arch:G=) != x86 ) ) || ( cygwin in $(props) ) + if ( cygwin in $(props) ) { configure.log-library-search-result "boost.stacktrace.from_exception" : "no" ; return no ; diff --git a/doc/stacktrace.qbk b/doc/stacktrace.qbk index 71ac73a..dd1a3a3 100644 --- a/doc/stacktrace.qbk +++ b/doc/stacktrace.qbk @@ -334,6 +334,17 @@ target_link_libraries(${PROJECT} # your project ) ``` +If Boost is installed into the system the best way to get it for your project +is via `find_package`: + +``` +find_package( + Boost + REQUIRED stacktrace stacktrace_from_exception + CONFIG +) +``` + [endsect] [section CMake build notes] diff --git a/src/from_exception.cpp b/src/from_exception.cpp index 366ba28..18f3001 100644 --- a/src/from_exception.cpp +++ b/src/from_exception.cpp @@ -160,29 +160,14 @@ BOOST_SYMBOL_EXPORT void assert_no_pending_traces() noexcept { #include #include + #if !BOOST_STACKTRACE_ALWAYS_STORE_IN_PADDING +#include +#include #include #include -#ifndef BOOST_STACKTRACE_LIBCXX_RUNTIME_MAY_CAUSE_MEMORY_LEAK - -#ifdef BOOST_HAS_THREADS - -#error On this platform memory leaks are possible if capturing stacktrace from \ - exceptions is enabled and exceptions are thrown concurrently \ - and libc++ runtime is used. \ - \ - Define `BOOST_STACKTRACE_LIBCXX_RUNTIME_MAY_CAUSE_MEMORY_LEAK` to \ - suppress this error if the library would not be used with libc++ \ - runtime (for example, it would be only used with GCC runtime). \ - \ - Otherwise, disable the boost_stacktrace_from_exception library build \ - (for example by `./b2 boost.stacktrace.from_exception=off` option). - -#endif - -#endif - +#include #endif namespace { @@ -297,6 +282,32 @@ void* __cxa_allocate_exception(size_t thrown_size) throw() { extern "C" BOOST_SYMBOL_EXPORT void __cxa_decrement_exception_refcount(void *thrown_object) throw() { BOOST_ASSERT(is_libcpp_runtime()); + +#if !defined(BOOST_STACKTRACE_LIBCXX_RUNTIME_MAY_CAUSE_MEMORY_LEAK) && defined(BOOST_HAS_THREADS) + static const char* leaks_are_fine = std::getenv("BOOST_STACKTRACE_LIBCXX_RUNTIME_MAY_CAUSE_MEMORY_LEAK"); + if (!leaks_are_fine || leaks_are_fine[0] != '1') { + const char* const warning = + "\n\n" + "=======================================================================================\n" + "\n" + "On this platform, memory leaks may occur if capturing stacktrace from exceptions is\n" + "enabled and exceptions are thrown concurrently by libc++ runtime (libc++abi).\n" + "\n" + "A proper workaround is to use libstdc++ runtime (libgcc_s) instead.\n" + "\n" + "Alternatively, if you are willing to accept potential MEMORY LEAKS, set the environment\n" + "variable `BOOST_STACKTRACE_LIBCXX_RUNTIME_MAY_CAUSE_MEMORY_LEAK=1` to proceed. You can\n" + "also define the `BOOST_STACKTRACE_LIBCXX_RUNTIME_MAY_CAUSE_MEMORY_LEAK` macro when\n" + "building the `boost_stacktrace_from_exception` library to disable this warning and to\n" + "get the MEMORY LEAKS silently on libc++ runtime.\n" + "\n" + "=======================================================================================\n" + ; + write(STDERR_FILENO, warning, std::strlen(warning)); + std::abort(); + } +#endif + if (!thrown_object) { return; } diff --git a/test/cmake_install_test/CMakeLists.txt b/test/cmake_install_test/CMakeLists.txt index cf4e67e..8cf4e29 100644 --- a/test/cmake_install_test/CMakeLists.txt +++ b/test/cmake_install_test/CMakeLists.txt @@ -2,14 +2,21 @@ # Distributed under the Boost Software License, Version 1.0. # https://www.boost.org/LICENSE_1_0.txt -cmake_minimum_required(VERSION 3.5...3.20) +cmake_minimum_required(VERSION 3.8...4.20) project(cmake_install_test LANGUAGES CXX) -find_package(boost_stacktrace REQUIRED) - +find_package( + Boost + REQUIRED stacktrace ${BOOST_STACKTRACE_IMPL_BACKEND} stacktrace_from_exception + CONFIG +) add_executable(main main.cpp) -target_link_libraries(main Boost::stacktrace) +target_link_libraries(main Boost::${BOOST_STACKTRACE_IMPL_BACKEND}) + +add_executable(main_from_exception main.cpp) +target_link_libraries(main_from_exception Boost::stacktrace_from_exception Boost::${BOOST_STACKTRACE_IMPL_BACKEND}) enable_testing() add_test(main main) +add_test(main_from_exception main_from_exception) diff --git a/test/cmake_install_test/main.cpp b/test/cmake_install_test/main.cpp index 28a5971..fc09a25 100644 --- a/test/cmake_install_test/main.cpp +++ b/test/cmake_install_test/main.cpp @@ -9,4 +9,9 @@ int main() { std::cout << boost::stacktrace::stacktrace() << std::endl; + try { + throw 42; + } catch (...) { + std::cout << "From current excption:\n" << boost::stacktrace::stacktrace::from_current_exception() << std::endl; + } }