From bb8da4303851642318b626aad507ab7c39f6a80d Mon Sep 17 00:00:00 2001
From: Alexey Tikhonov <atikhono@redhat.com>
Date: Mon, 1 Nov 2021 20:09:02 +0100
Subject: [PATCH] DEBUG: avoid backtrace dups.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
In case the same error(s) is repeated again and again repeating the same
backtrace doesn't add much value. In this case let's add just a note.
Reviewed-by: Tomáš Halman <thalman@redhat.com>
---
src/util/debug.c | 4 +--
src/util/debug_backtrace.c | 51 +++++++++++++++++++++++++++++++++++---
2 files changed, 50 insertions(+), 5 deletions(-)
diff --git a/src/util/debug.c b/src/util/debug.c
index 7c03fb7df..953123718 100644
--- a/src/util/debug.c
+++ b/src/util/debug.c
@@ -42,7 +42,7 @@
void sss_debug_backtrace_init(void);
void sss_debug_backtrace_vprintf(int level, const char *format, va_list ap);
void sss_debug_backtrace_printf(int level, const char *format, ...);
-void sss_debug_backtrace_endmsg(int level);
+void sss_debug_backtrace_endmsg(const char *file, long line, int level);
const char *debug_prg_name = "sssd";
@@ -359,7 +359,7 @@ void sss_vdebug_fn(const char *file,
if (flags & APPEND_LINE_FEED) {
sss_debug_backtrace_printf(level, "\n");
}
- sss_debug_backtrace_endmsg(level);
+ sss_debug_backtrace_endmsg(file, line, level);
}
void sss_debug_fn(const char *file,
diff --git a/src/util/debug_backtrace.c b/src/util/debug_backtrace.c
index d99325ab6..e376f815b 100644
--- a/src/util/debug_backtrace.c
+++ b/src/util/debug_backtrace.c
@@ -30,6 +30,9 @@ extern FILE *_sss_debug_file;
static const unsigned SSS_DEBUG_BACKTRACE_DEFAULT_SIZE = 100*1024; /* bytes */
static const unsigned SSS_DEBUG_BACKTRACE_LEVEL = SSSDBG_BE_FO;
+/* Size of locations history to keep to avoid duplicating backtraces */
+#define SSS_DEBUG_BACKTRACE_LOCATIONS 5
+
/* -->
* ring buffer = [*******t...\n............e000]
@@ -46,12 +49,21 @@ static struct {
char *buffer; /* buffer start */
char *end; /* end data border */
char *tail; /* tail of "current" message */
+
+ /* locations where last backtraces happened */
+ struct {
+ const char *file;
+ long line;
+ } locations[SSS_DEBUG_BACKTRACE_LOCATIONS];
+ unsigned last_location_idx;
} _bt;
static inline bool _all_levels_enabled(void);
static inline bool _backtrace_is_enabled(int level);
static inline bool _is_trigger_level(int level);
+static void _store_location(const char *file, long line);
+static bool _is_recent_location(const char *file, long line);
static void _backtrace_vprintf(const char *format, va_list ap);
static void _backtrace_printf(const char *format, ...);
static void _backtrace_dump(void);
@@ -75,6 +87,8 @@ void sss_debug_backtrace_init(void)
_bt.enabled = true;
_bt.initialized = true;
+ /* locations[] & last_location_idx are zero-initialized */
+
_backtrace_printf(" * ");
}
@@ -116,7 +130,7 @@ void sss_debug_backtrace_printf(int level, const char *format, ...)
}
-void sss_debug_backtrace_endmsg(int level)
+void sss_debug_backtrace_endmsg(const char *file, long line, int level)
{
if (DEBUG_IS_SET(level)) {
_debug_fflush();
@@ -124,7 +138,16 @@ void sss_debug_backtrace_endmsg(int level)
if (_backtrace_is_enabled(level)) {
if (_is_trigger_level(level)) {
- _backtrace_dump();
+ if (!_is_recent_location(file, line)) {
+ _backtrace_dump();
+ _store_location(file, line);
+ } else {
+ fprintf(_sss_debug_file ? _sss_debug_file : stderr,
+ " * ... skipping repetitive backtrace ...\n");
+ /* and reset */
+ _bt.end = _bt.buffer;
+ _bt.tail = _bt.buffer;
+ }
}
_backtrace_printf(" * ");
}
@@ -191,7 +214,29 @@ static inline bool _backtrace_is_enabled(int level)
}
- /* prints to buffer */
+static void _store_location(const char *file, long line)
+{
+ _bt.last_location_idx = (_bt.last_location_idx + 1) % SSS_DEBUG_BACKTRACE_LOCATIONS;
+ /* __FILE__ is a character string literal with static storage duration. */
+ _bt.locations[_bt.last_location_idx].file = file;
+ _bt.locations[_bt.last_location_idx].line = line;
+}
+
+
+static bool _is_recent_location(const char *file, long line)
+{
+ for (unsigned idx = 0; idx < SSS_DEBUG_BACKTRACE_LOCATIONS; ++idx) {
+ if ((line == _bt.locations[idx].line) &&
+ (_bt.locations[idx].file != NULL) &&
+ (strcmp(file, _bt.locations[idx].file) == 0)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/* prints to buffer */
static void _backtrace_vprintf(const char *format, va_list ap)
{
int buff_tail_size = _bt.size - (_bt.tail - _bt.buffer);
--
2.26.3