-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[lldb] Make lldbassert fire only once per instance #134343
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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
@llvm/pr-subscribers-lldb Author: Jonas Devlieghere (JDevlieghere) ChangesThe Recently, we ran into an issue where an Once an rdar://148520448 Full diff: https://github.com/llvm/llvm-project/pull/134343.diff 2 Files Affected:
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) {
|
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 (cherry picked from commit 03604a7)
…4b04b411903-03604a784011 [🍒 stable/20240723] [lldb] Make lldbassert fire only once per instance (llvm#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 (cherry picked from commit 03604a7)
The
lldbassert
macro in LLDB behaves like a regularassert
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 staticstd::once_flag
in the macro. This way, everylldbasser
will fire at most once per lldb instance.rdar://148520448