From ad1828c13b593914c3f489b8ba116b179d2db78a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gonzalo=20Garramu=C3=B1o?= Date: Thu, 25 Apr 2024 17:15:31 -0300 Subject: [PATCH] Added linux stack trace with files and line numbers. --- .github/workflows/full_linux.yml | 16 +++-- .github/workflows/full_macos12.yml | 18 ++++-- .github/workflows/full_macos14.yml | 16 +++-- .github/workflows/full_win64.yml | 16 +++-- CMakeLists.txt | 7 ++- bin/runme_minimal.sh | 2 +- cmake/Modules/BuildGettext.cmake | 12 ---- cmake/Modules/Buildlibbacktrace.cmake | 17 ++++++ cmake/Modules/Buildmrv2.cmake | 7 +-- etc/build_dir.sh | 2 +- etc/parse_args.sh | 7 ++- mrv2/CMakeLists.txt | 4 ++ mrv2/docs/HISTORY.md | 1 + mrv2/docs/Legal/LICENSE_libbacktrace.txt | 31 ++++++++++ mrv2/lib/mrvApp/mrvApp.cpp | 4 +- mrv2/lib/mrvCore/CMakeLists.txt | 3 +- mrv2/lib/mrvCore/Linux/mrvStackTrace.cpp | 76 ++++++++++++++---------- mrv2/lib/mrvWidgets/mrvVersion.cpp | 6 ++ mrv2/src/CMakeLists.txt | 2 +- runme_nolog.sh | 8 +-- 20 files changed, 173 insertions(+), 82 deletions(-) create mode 100644 cmake/Modules/Buildlibbacktrace.cmake create mode 100644 mrv2/docs/Legal/LICENSE_libbacktrace.txt diff --git a/.github/workflows/full_linux.yml b/.github/workflows/full_linux.yml index c43f8741f..6dfe14c5e 100644 --- a/.github/workflows/full_linux.yml +++ b/.github/workflows/full_linux.yml @@ -83,7 +83,15 @@ jobs: run: | ./runme_nolog.sh -t package - - name: Upload binaries - run: | - ./bin/upload_sourceforge.sh - + - name: Get repository owner # Name of the step + run: | # Multi-line command definition + owner_name=${{ github.repository.owner.login }} + echo "The repository owner is: $owner_name" + + - name: Upload binaries # Conditional step + run: | # Multi-line command definition + if [[ $owner_name == 'ggarra13' ]]; then + # Your commands to be executed only for ggarra13 + ./bin/upload_sourceforge.sh + fi + shell: bash diff --git a/.github/workflows/full_macos12.yml b/.github/workflows/full_macos12.yml index 726f0eaf8..2649520a6 100644 --- a/.github/workflows/full_macos12.yml +++ b/.github/workflows/full_macos12.yml @@ -59,9 +59,17 @@ jobs: - name: Build mrv2 run: | - ./runme_nolog.sh -t package - - - name: Upload binaries - run: | - ./bin/upload_sourceforge.sh + ./runme_nolog.sh -j 1 -t package + - name: Get repository owner # Name of the step + run: | # Multi-line command definition + owner_name=${{ github.repository.owner.login }} + echo "The repository owner is: $owner_name" + + - name: Upload binaries # Conditional step + run: | # Multi-line command definition + if [[ $owner_name == 'ggarra13' ]]; then + # Your commands to be executed only for ggarra13 + ./bin/upload_sourceforge.sh + fi + shell: bash diff --git a/.github/workflows/full_macos14.yml b/.github/workflows/full_macos14.yml index fc8c03ce6..6934a0e72 100644 --- a/.github/workflows/full_macos14.yml +++ b/.github/workflows/full_macos14.yml @@ -67,7 +67,15 @@ jobs: run: | ./runme_nolog.sh -t package - - name: Upload binaries - run: | - ./bin/upload_sourceforge.sh - + - name: Get repository owner # Name of the step + run: | # Multi-line command definition + owner_name=${{ github.repository.owner.login }} + echo "The repository owner is: $owner_name" + + - name: Upload binaries # Conditional step + run: | # Multi-line command definition + if [[ $owner_name == 'ggarra13' ]]; then + # Your commands to be executed only for ggarra13 + ./bin/upload_sourceforge.sh + fi + shell: bash diff --git a/.github/workflows/full_win64.yml b/.github/workflows/full_win64.yml index c56cb9a47..53d8dac52 100644 --- a/.github/workflows/full_win64.yml +++ b/.github/workflows/full_win64.yml @@ -66,7 +66,15 @@ jobs: run: | ./runme_nolog.sh -t package -D TLRENDER_USD=OFF - - name: Upload binaries - run: | - ./bin/upload_sourceforge.sh - + - name: Get repository owner # Name of the step + run: | # Multi-line command definition + owner_name=${{ github.repository.owner.login }} + echo "The repository owner is: $owner_name" + + - name: Upload binaries # Conditional step + run: | # Multi-line command definition + if [[ $owner_name == 'ggarra13' ]]; then + # Your commands to be executed only for ggarra13 + ./bin/upload_sourceforge.sh + fi + shell: bash diff --git a/CMakeLists.txt b/CMakeLists.txt index 9fa492c37..f3f2e4140 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,8 +90,7 @@ else() endif() endif() - - set(PYTHON_EXECUTABLE ${Python_EXECUTABLE} ) +set(PYTHON_EXECUTABLE ${Python_EXECUTABLE} ) if(CMAKE_BUILD_TYPE MATCHES "^Debug$") # Check for Clang or GCC compiler (@todo: add Microsoft support) @@ -121,6 +120,10 @@ elseif(APPLE) endif() endif() +set(libbacktrace_DEP ) +if(UNIX AND NOT APPLE) + include( cmake/Modules/Buildlibbacktrace.cmake ) +endif() set( PYBIND11_DEP ) if( MRV2_PYBIND11 ) diff --git a/bin/runme_minimal.sh b/bin/runme_minimal.sh index a51cc4490..f22a79c22 100644 --- a/bin/runme_minimal.sh +++ b/bin/runme_minimal.sh @@ -27,7 +27,7 @@ params=$* # . etc/build_dir.sh -export BUILD_DIR=BUILD-$KERNEL-$ARCH-minimal/${CMAKE_BUILD_TYPE} +export BUILD_DIR=BUILD-$KERNEL-$ARCH-minimal/${BUILD_TYPE_DIR} mkdir -p $BUILD_DIR diff --git a/cmake/Modules/BuildGettext.cmake b/cmake/Modules/BuildGettext.cmake index bd6a29ece..d0656c7a8 100644 --- a/cmake/Modules/BuildGettext.cmake +++ b/cmake/Modules/BuildGettext.cmake @@ -41,16 +41,4 @@ ExternalProject_Add( BUILD_IN_SOURCE 1 ) - -# ExternalProject_Add( -# GETTEXT -# URL "https://ftp.gnu.org/gnu/gettext/gettext-0.21.1.tar.gz" -# CONFIGURE_COMMAND "" -# BUILD_COMMAND "" -# INSTALL_COMMAND "true" -# BUILD_IN_SOURCE 1 -# ) - - - set( Gettext GETTEXT ) diff --git a/cmake/Modules/Buildlibbacktrace.cmake b/cmake/Modules/Buildlibbacktrace.cmake new file mode 100644 index 000000000..ad590dffb --- /dev/null +++ b/cmake/Modules/Buildlibbacktrace.cmake @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: BSD-3-Clause +# mrv2 +# Copyright Contributors to the mrv2 Project. All rights reserved. + +include( ExternalProject ) + +set(libbacktrace_TAG master) + +ExternalProject_Add( + libbacktrace + GIT_REPOSITORY "https://github.com/ianlancetaylor/libbacktrace.git" + GIT_TAG ${libbacktrace_TAG} + CONFIGURE_COMMAND ./configure --prefix=${CMAKE_INSTALL_PREFIX} + BUILD_IN_SOURCE 1 +) + +set( libbacktrace_DEP libbacktrace ) diff --git a/cmake/Modules/Buildmrv2.cmake b/cmake/Modules/Buildmrv2.cmake index 709264c3f..6f1d41651 100644 --- a/cmake/Modules/Buildmrv2.cmake +++ b/cmake/Modules/Buildmrv2.cmake @@ -16,7 +16,6 @@ set(mrv2_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_MESSAGE=${CMAKE_INSTALL_MESSAGE} - -DTLRENDER_PYTHON=${TLRENDER_PYTHON} -DTLRENDER_API=${TLRENDER_API} -DTLRENDER_BMD=${TLRENDER_BMD} -DTLRENDER_BMD_SDK=${TLRENDER_BMD_SDK} @@ -43,16 +42,12 @@ set(mrv2_ARGS -DMRV2_PYBIND11=${MRV2_PYBIND11} -DMRV2_PDF=${MRV2_PDF} -DMRV2_PYFLTK=${MRV2_PYFLTK} - - -DFLTK_BACKEND_WAYLAND=${FLTK_BACKEND_WAYLAND} - -DFLTK_BACKEND_X11=${FLTK_BACKEND_X11} - -DFLTK_BUILD_SHARED_LIBS=${FLTK_BUILD_SHARED_LIBS} ) ExternalProject_Add( mrv2 PREFIX ${CMAKE_CURRENT_BINARY_DIR}/mrv2 - DEPENDS tlRender ${FLTK_DEP} ${PYTHON_DEP} ${PYBIND11_DEP} ${pyFLTK_DEP} ${POCO_DEP} ${LibHaru_DEP} ${Gettext} + DEPENDS tlRender ${FLTK_DEP} ${PYTHON_DEP} ${PYBIND11_DEP} ${pyFLTK_DEP} ${POCO_DEP} ${LibHaru_DEP} ${Gettext} ${libbacktrace_DEP} SOURCE_DIR ${CMAKE_SOURCE_DIR}/mrv2 LIST_SEPARATOR | CMAKE_ARGS ${mrv2_ARGS} diff --git a/etc/build_dir.sh b/etc/build_dir.sh index 4e68743bb..2d70aecb8 100755 --- a/etc/build_dir.sh +++ b/etc/build_dir.sh @@ -33,7 +33,7 @@ extract_python_version # # Build a build directory with that information # -export BUILD_DIR=$BUILD_ROOT/${CMAKE_BUILD_TYPE} +export BUILD_DIR=$BUILD_ROOT/${BUILD_TYPE_DIR} # # Clean the directory if we were asked to. diff --git a/etc/parse_args.sh b/etc/parse_args.sh index ab40f025a..69062dc46 100755 --- a/etc/parse_args.sh +++ b/etc/parse_args.sh @@ -71,7 +71,8 @@ export TLRENDER_X264=OFF CLEAN_DIR=0 export CMAKE_OSX_ARCHITECTURES="" export CMAKE_VERBOSE_MAKEFILE=OFF -export CMAKE_BUILD_TYPE="Release" +export BUILD_TYPE_DIR="Release" +export CMAKE_BUILD_TYPE="RelWithDebInfo" export CMAKE_GENERATOR="Ninja" export CMAKE_TARGET="" ASK_TO_CONTINUE=0 @@ -79,11 +80,13 @@ ASK_TO_CONTINUE=0 for i in "$@"; do case $i in release|Release) - export CMAKE_BUILD_TYPE="Release" + export CMAKE_BUILD_TYPE="RelWithDebInfo" + export BUILD_TYPE_DIR="Release" shift ;; debug|Debug) export CMAKE_BUILD_TYPE="Debug" + export BUILD_TYPE_DIR="Debug" export CMAKE_FLAGS=" -DTLRENDER_API=GL_4_1_Debug" shift ;; diff --git a/mrv2/CMakeLists.txt b/mrv2/CMakeLists.txt index 62a58a91e..ca2cdcd55 100644 --- a/mrv2/CMakeLists.txt +++ b/mrv2/CMakeLists.txt @@ -79,6 +79,10 @@ if( MRV2_PDF ) add_definitions( -DMRV2_PDF ) endif() +if(UNIX AND NOT APPLE) + find_library(backtrace NAMES backtrace) +endif() + if(TLRENDER_BMD) add_definitions(-DTLRENDER_BMD) endif() diff --git a/mrv2/docs/HISTORY.md b/mrv2/docs/HISTORY.md index 7130851a6..db996a619 100644 --- a/mrv2/docs/HISTORY.md +++ b/mrv2/docs/HISTORY.md @@ -15,6 +15,7 @@ v1.1.4 - Fixed floating values not respecting float values below 0 or higher than 1. - Improved the performance of OpenGL drawing on Windows and Linux by using blitting. +- Added Linux's stack traces with line numbers by relying on libbacktrace. v1.1.3 diff --git a/mrv2/docs/Legal/LICENSE_libbacktrace.txt b/mrv2/docs/Legal/LICENSE_libbacktrace.txt new file mode 100644 index 000000000..5f3ddb018 --- /dev/null +++ b/mrv2/docs/Legal/LICENSE_libbacktrace.txt @@ -0,0 +1,31 @@ +backtrace.h -- Public header file for stack backtrace library. +Copyright (C) 2012-2021 Free Software Foundation, Inc. +Written by Ian Lance Taylor, Google. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + (1) Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + (2) Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + (3) The name of the author may not be used to + endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/mrv2/lib/mrvApp/mrvApp.cpp b/mrv2/lib/mrvApp/mrvApp.cpp index eaca29c47..c721ed8d8 100644 --- a/mrv2/lib/mrvApp/mrvApp.cpp +++ b/mrv2/lib/mrvApp/mrvApp.cpp @@ -242,7 +242,7 @@ namespace mrv _p(new Private) { TLRENDER_P(); - + // Establish MRV2_ROOT environment variable set_root_path(argc, argv); @@ -1014,7 +1014,7 @@ namespace mrv } for (const auto& path : - timeline::getPaths(filePath, pathOptions, _context)) + timeline::getPaths(filePath, pathOptions, _context)) { auto item = std::make_shared(); item->path = path; diff --git a/mrv2/lib/mrvCore/CMakeLists.txt b/mrv2/lib/mrvCore/CMakeLists.txt index fb7949cab..017b9bc9c 100644 --- a/mrv2/lib/mrvCore/CMakeLists.txt +++ b/mrv2/lib/mrvCore/CMakeLists.txt @@ -69,10 +69,11 @@ elseif( APPLE ) # macOS/mrvStackTrace.cpp # macOS/mrvSignalHandler.cpp) else() - list( APPEND SOURCES + list(APPEND SOURCES mrvFileManager.cpp Linux/mrvStackTrace.cpp Linux/mrvSignalHandler.cpp) + list(APPEND LIBRARIES_PRIVATE backtrace) endif() add_library(mrvCore ${SOURCES} ${HEADERS}) diff --git a/mrv2/lib/mrvCore/Linux/mrvStackTrace.cpp b/mrv2/lib/mrvCore/Linux/mrvStackTrace.cpp index 6e81ede1e..f07b551dd 100644 --- a/mrv2/lib/mrvCore/Linux/mrvStackTrace.cpp +++ b/mrv2/lib/mrvCore/Linux/mrvStackTrace.cpp @@ -1,39 +1,53 @@ +#include +#include +#include +#include -#include -#include -#include +#include -void printStackTrace() +void error_callback(void* data, const char* msg, int errnum) { - void* callstack[128]; - int frames = backtrace(callstack, 128); - char** symbols = backtrace_symbols(callstack, frames); - - // Skip first frame which is this stack trace function - for (int i = 1; i < frames; i++) - { - printf("frame %d: ", i); - - // Use addr2line and c++filt to get the demangled symbol and line number - char exe[256]; - snprintf(exe, 256, "%s/bin/mrv2", getenv("MRV2_ROOT")); - - char command[1024]; - snprintf( - command, sizeof(command), "addr2line -e %s %p | c++filt", exe, - callstack[i]); - FILE* fp = popen(command, "r"); - - char output[512]; - if (fgets(output, sizeof(output), fp) != nullptr) - printf("%s", output); - - pclose(fp); + fprintf(stderr, "%s - Error %d\n", msg, errnum); +} - // Print the raw symbol as well - printf(" %s\n", symbols[i]); +int full_callback( + void* data, uintptr_t pc, const char* filename, int lineno, + const char* function) +{ + char demangled_name[1024]; + demangled_name[0] = '\0'; + + + char buffer[512]; + if (!filename || !function || strcmp(function, "(null)") == 0) + return 0; + + snprintf(buffer, sizeof(buffer), "c++filt %s", function); + FILE* pipe = popen(buffer, "r"); + if (!pipe) { + perror("popen"); + return 1; } + fgets(demangled_name, sizeof(demangled_name), pipe); + pclose(pipe); + + size_t len = strlen(demangled_name); + if (len > 0) + demangled_name[len-1] = '\0'; + + printf("0x%lx %s (%s:%d)\n", pc, demangled_name, filename, lineno); + return 0; +} + +void printStackTrace() +{ + // MRV2_ROOT contains the root path of the executable. + char exe[1024]; + snprintf(exe, 1024, "%s/bin/mrv2", getenv("MRV2_ROOT")); - free(symbols); + auto state = backtrace_create_state(exe, 1, error_callback, nullptr); + int ret = backtrace_full(state, 0, full_callback, error_callback, nullptr); + } + diff --git a/mrv2/lib/mrvWidgets/mrvVersion.cpp b/mrv2/lib/mrvWidgets/mrvVersion.cpp index f8564f83e..2178a0b50 100644 --- a/mrv2/lib/mrvWidgets/mrvVersion.cpp +++ b/mrv2/lib/mrvWidgets/mrvVersion.cpp @@ -815,6 +815,12 @@ namespace mrv << endl; #ifdef TLRENDER_TIFF o << TIFFLIB_VERSION_STR << endl << endl; +#endif +#ifdef __linux__ + o << "libbacktrace v1.0" << endl + << "Copyright (C) 2012-2021 Free Software Foundation, Inc." << endl + << "Written by Ian Lance Taylor, Google." << endl + << endl; #endif o << "LibVPX" << endl << "Copyright (c) 2010, The WebM Project authors. All rights " diff --git a/mrv2/src/CMakeLists.txt b/mrv2/src/CMakeLists.txt index c60c9ca9c..fc770cfe9 100644 --- a/mrv2/src/CMakeLists.txt +++ b/mrv2/src/CMakeLists.txt @@ -53,7 +53,7 @@ if(WIN32) elseif(APPLE) set(PRUNE_SYMBOLS "-Wl,-dead_strip") else(UNIX) - set(PRUNE_SYMBOLS "-Wl,--gc-sections") + #set(PRUNE_SYMBOLS "-Wl,--gc-sections") endif() target_link_options(mrv2 PRIVATE ${PRUNE_SYMBOLS}) diff --git a/runme_nolog.sh b/runme_nolog.sh index 37f060edb..a1a84ebf0 100755 --- a/runme_nolog.sh +++ b/runme_nolog.sh @@ -199,23 +199,19 @@ fi mkdir -p $BUILD_DIR/install - + # # Handle Windows pre-flight compiles # -export ACTUAL_BUILD_TYPE=${CMAKE_BUILD_TYPE} if [[ $KERNEL == *Msys* ]]; then . $PWD/etc/compile_windows_dlls.sh - if [[ $CMAKE_BUILD_TYPE == Release ]]; then - export ACTUAL_BUILD_TYPE=RelWithDebInfo - fi fi cd $BUILD_DIR cmd="cmake -G '${CMAKE_GENERATOR}' \ - -D CMAKE_BUILD_TYPE=${ACTUAL_BUILD_TYPE} \ + -D CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} \ -D CMAKE_INSTALL_PREFIX=$PWD/install \ -D CMAKE_PREFIX_PATH=$PWD/install \ -D BUILD_PYTHON=${BUILD_PYTHON} \