From 774c6d5ef2d4a2b68e6849f05484b3158e6b6705 Mon Sep 17 00:00:00 2001 From: Dmitriy Suponitskiy Date: Thu, 6 Jun 2024 16:31:29 -0400 Subject: [PATCH 1/2] Fixed tcmalloc crashes --- src/core/include/utils/demangle.h | 2 +- src/core/include/utils/get-call-stack.h | 5 +++-- src/core/lib/utils/demangle.cpp | 15 +++++++++++---- src/core/lib/utils/get-call-stack.cpp | 20 ++++++++++++-------- 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/core/include/utils/demangle.h b/src/core/include/utils/demangle.h index b12793b66..751b56bd4 100644 --- a/src/core/include/utils/demangle.h +++ b/src/core/include/utils/demangle.h @@ -33,6 +33,6 @@ #include -std::string demangle(const char* name); +std::string demangle(const char* name) noexcept; #endif // __DEMANGLE_H__ diff --git a/src/core/include/utils/get-call-stack.h b/src/core/include/utils/get-call-stack.h index 2481470c2..b54ca1d3d 100644 --- a/src/core/include/utils/get-call-stack.h +++ b/src/core/include/utils/get-call-stack.h @@ -35,9 +35,10 @@ #include /** - * @brief get_call_stack() is a function to get the call stack + * @brief get_call_stack() is a function to get the call stack. + * @attention it must not throw an exception as it is called from OpenFHEException * @return a vector with call stack (demangled function names) */ -std::vector get_call_stack(); +std::vector get_call_stack() noexcept; #endif // __GET_CALL_STACK_H__ diff --git a/src/core/lib/utils/demangle.cpp b/src/core/lib/utils/demangle.cpp index 6be50c5f8..ab3aab01a 100644 --- a/src/core/lib/utils/demangle.cpp +++ b/src/core/lib/utils/demangle.cpp @@ -34,11 +34,18 @@ #if defined(__clang__) || defined(__GNUC__) #include -std::string demangle(const char* const name) { - int status = -1; - std::unique_ptr result{abi::__cxa_demangle(name, NULL, NULL, &status)}; +std::string demangle(const char* const name) noexcept { + // output_buffer must be malloc'ed + size_t output_buffer_size = 512; + auto output_buffer = reinterpret_cast(std::malloc(output_buffer_size)); + int status = -1; + + const char* ptr = abi::__cxa_demangle(name, output_buffer, &output_buffer_size, &status); + + std::string result{((status == 0) && (ptr != NULL)) ? ptr : (std::string("Can not demangle symbol: ") + name)}; + free(output_buffer); - return (status == 0) ? result.get() : (std::string("Can not demangle symbol: ") + name); + return result; } #else std::string demangle(const char* const name) { diff --git a/src/core/lib/utils/get-call-stack.cpp b/src/core/lib/utils/get-call-stack.cpp index 28c049021..e53f5ac07 100644 --- a/src/core/lib/utils/get-call-stack.cpp +++ b/src/core/lib/utils/get-call-stack.cpp @@ -31,7 +31,7 @@ #include "utils/get-call-stack.h" #if defined(__linux__) && defined(__GNUC__) -// clang-format off + // clang-format off #include "utils/demangle.h" #include @@ -43,7 +43,7 @@ namespace { enum { MAX_BACKTRACE_ADDRESSES = 512 }; } -static bool stringEmpty(const std::string& str) { +static bool stringEmpty(const std::string& str) noexcept { if (!str.length()) return true; @@ -56,18 +56,21 @@ static bool stringEmpty(const std::string& str) { return true; } -std::vector get_call_stack() { +std::vector get_call_stack() noexcept { void* bt_buffer[MAX_BACKTRACE_ADDRESSES] = {NULL}; const int n = backtrace(bt_buffer, MAX_BACKTRACE_ADDRESSES); if (n < 1) { return std::vector(); } - const std::unique_ptr symbols(backtrace_symbols(bt_buffer, n)); + char** symbols = reinterpret_cast(backtrace_symbols(bt_buffer, n)); + if (symbols == NULL) { + return std::vector(); + } const size_t numSymbols = static_cast(n); - std::vector ret(numSymbols); + std::vector retVec(numSymbols); for (size_t i = 0; i < numSymbols; ++i) { - std::string symbol(symbols.get()[i]); + std::string symbol(symbols[i]); // we need to get rid of anything that doesn't belong to the name // Mangled symbol examples: // ./lib/libOPENFHEcore.so.1(_Z14get_call_stackB5cxx11v+0x35) [0x7f1b5cdb91d5] @@ -81,10 +84,11 @@ std::vector get_call_stack() { size_t newLen = symbol.length() - pos; std::string mangledName(symbol.substr(pos + 1, newLen)); - ret[i] = (stringEmpty(mangledName)) ? symbols.get()[i] : demangle(mangledName.c_str()); + retVec[i] = (stringEmpty(mangledName)) ? symbols[i] : demangle(mangledName.c_str()); } - return ret; + free(symbols); + return retVec; } #else std::vector get_call_stack() { From d1bbb81c2c917c7549f29f599f92c8c7d9be7582 Mon Sep 17 00:00:00 2001 From: Dmitriy Suponitskiy Date: Fri, 7 Jun 2024 11:41:35 -0400 Subject: [PATCH 2/2] Corrected the code of demangle() --- src/core/lib/utils/demangle.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/core/lib/utils/demangle.cpp b/src/core/lib/utils/demangle.cpp index ab3aab01a..ee476a160 100644 --- a/src/core/lib/utils/demangle.cpp +++ b/src/core/lib/utils/demangle.cpp @@ -40,15 +40,25 @@ std::string demangle(const char* const name) noexcept { auto output_buffer = reinterpret_cast(std::malloc(output_buffer_size)); int status = -1; - const char* ptr = abi::__cxa_demangle(name, output_buffer, &output_buffer_size, &status); - - std::string result{((status == 0) && (ptr != NULL)) ? ptr : (std::string("Can not demangle symbol: ") + name)}; - free(output_buffer); + char* ptr = abi::__cxa_demangle(name, output_buffer, &output_buffer_size, &status); + std::string result; + if (status == 0 && ptr != nullptr) { + result = ptr; + // If ptr is different from output_buffer, free ptr as it points to the newly allocated (realloc) buffer + if (ptr != output_buffer) + std::free(ptr); + else + std::free(output_buffer); + } + else { + result = "Cannot demangle symbol: " + std::string(name); + std::free(output_buffer); + } return result; } #else -std::string demangle(const char* const name) { +std::string demangle(const char* const name) noexcept { return name; } #endif