Author: Jonas Devlieghere Date: 2025-04-04T12:53:10-07:00 New Revision: 03604a784011bec2292f900b118d825f34f8cf89
URL: https://github.com/llvm/llvm-project/commit/03604a784011bec2292f900b118d825f34f8cf89 DIFF: https://github.com/llvm/llvm-project/commit/03604a784011bec2292f900b118d825f34f8cf89.diff LOG: [lldb] Make lldbassert fire only once per instance (#134343) The `lldbassert` macro in LLDB behaves like a regular `assert` when assertions are enabled, and otherwise prints a pretty backtrace and prompts the user to file a bug. By default, this is emitted as a diagnostic event, but vendors can provide their own behavior, for example pre-populating a bug report. Recently, we ran into an issue where an `lldbassert` (in the Swift language plugin) would fire excessively, to the point that it was interfering with the usability of the debugger. Once an `lldbasser` has fired, there's no point in bothering the user over and over again for the same problem. This PR solves the problem by introducing a static `std::once_flag` in the macro. This way, every `lldbasser` will fire at most once per lldb instance. rdar://148520448 Added: Modified: lldb/include/lldb/Utility/LLDBAssert.h lldb/source/Utility/LLDBAssert.cpp Removed: ################################################################################ diff --git a/lldb/include/lldb/Utility/LLDBAssert.h b/lldb/include/lldb/Utility/LLDBAssert.h index 21dbdb3b3202d..cee30b81402ca 100644 --- a/lldb/include/lldb/Utility/LLDBAssert.h +++ b/lldb/include/lldb/Utility/LLDBAssert.h @@ -10,6 +10,7 @@ #define LLDB_UTILITY_LLDBASSERT_H #include "llvm/ADT/StringRef.h" +#include <mutex> #ifndef NDEBUG #define lldbassert(x) assert(x) @@ -19,8 +20,11 @@ // __FILE__ but only renders the last path component (the filename) instead of // an invocation dependent full path to that file. #define lldbassert(x) \ - lldb_private::_lldb_assert(static_cast<bool>(x), #x, __FUNCTION__, \ - __FILE_NAME__, __LINE__) + do { \ + static std::once_flag _once_flag; \ + lldb_private::_lldb_assert(static_cast<bool>(x), #x, __FUNCTION__, \ + __FILE_NAME__, __LINE__, _once_flag) \ + } while (0) #else #define lldbassert(x) \ lldb_private::_lldb_assert(static_cast<bool>(x), #x, __FUNCTION__, __FILE__, \ @@ -33,7 +37,8 @@ namespace lldb_private { /// Don't use _lldb_assert directly. Use the lldbassert macro instead so that /// LLDB asserts become regular asserts in NDEBUG builds. void _lldb_assert(bool expression, const char *expr_text, const char *func, - const char *file, unsigned int line); + const char *file, unsigned int line, + std::once_flag &once_flag); /// The default LLDB assert callback, which prints to stderr. typedef void (*LLDBAssertCallback)(llvm::StringRef message, diff --git a/lldb/source/Utility/LLDBAssert.cpp b/lldb/source/Utility/LLDBAssert.cpp index b84c581ccf822..611ad43cd071b 100644 --- a/lldb/source/Utility/LLDBAssert.cpp +++ b/lldb/source/Utility/LLDBAssert.cpp @@ -11,6 +11,7 @@ #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Signals.h" #include "llvm/Support/raw_ostream.h" +#include <mutex> #if LLVM_SUPPORT_XCODE_SIGNPOSTS #include <os/log.h> @@ -33,29 +34,33 @@ static std::atomic<LLDBAssertCallback> g_lldb_assert_callback = &DefaultAssertCallback; void _lldb_assert(bool expression, const char *expr_text, const char *func, - const char *file, unsigned int line) { + const char *file, unsigned int line, + std::once_flag &once_flag) { if (LLVM_LIKELY(expression)) return; + std::call_once(once_flag, [&]() { #if LLVM_SUPPORT_XCODE_SIGNPOSTS - if (__builtin_available(macos 10.12, iOS 10, tvOS 10, watchOS 3, *)) { - os_log_fault(OS_LOG_DEFAULT, - "Assertion failed: (%s), function %s, file %s, line %u\n", - expr_text, func, file, line); - } + if (__builtin_available(macos 10.12, iOS 10, tvOS 10, watchOS 3, *)) { + os_log_fault(OS_LOG_DEFAULT, + "Assertion failed: (%s), function %s, file %s, line %u\n", + expr_text, func, file, line); + } #endif - std::string buffer; - llvm::raw_string_ostream backtrace(buffer); - llvm::sys::PrintStackTrace(backtrace); + std::string buffer; + llvm::raw_string_ostream backtrace(buffer); + llvm::sys::PrintStackTrace(backtrace); - (*g_lldb_assert_callback.load())( - llvm::formatv("Assertion failed: ({0}), function {1}, file {2}, line {3}", - expr_text, func, file, line) - .str(), - buffer, - "Please file a bug report against lldb and include the backtrace, the " - "version and as many details as possible."); + (*g_lldb_assert_callback.load())( + llvm::formatv( + "Assertion failed: ({0}), function {1}, file {2}, line {3}", + expr_text, func, file, line) + .str(), + buffer, + "Please file a bug report against lldb and include the backtrace, the " + "version and as many details as possible."); + }); } void SetLLDBAssertCallback(LLDBAssertCallback callback) { _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits