From: Willy Tarreau Date: Tue, 11 Aug 2026 12:20:45 +0000 (+0200) Subject: MEDIUM: debug: do not dump a context-less backtrace in ABORT_NOW() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=577465a5f67834d7da2b8a7e36de58743af72a3e;p=thirdparty%2Fhaproxy.git MEDIUM: debug: do not dump a context-less backtrace in ABORT_NOW() Originally before 2.4, ABORT_NOW() was used to instantly stop the program with as little damage as possible in order to help debug it, keeping registers intact. This was modified in 2.4-dev6 by commit 5baf4fe31ad ("MEDIUM: debug: now always print a backtrace on CRASH_NOW() and friends") because the same macro was shared with BUG_ON() and we didn't have the backtrace. But by doing this we lost the ability to debug the precise crash location. Later in 3.0, we added support for an extra contextual info with commit d417863828 ("MINOR: debug: support passing an optional message in ABORT_NOW()"). This became even more fishy because at this point, ABORT_NOW() called empty would only emit a backtrace, while when passed an argument, it would emit "ABORT at :: ", losing the registers despite what the comment would say. Now that we can type call places, it becomes possible to fix it again so that ABORT_NOW() honors its two promises: - no register mangling when called with no argument ; - location + backtrace + message when called with an argument. This patch simply conditions the call to ha_backtrace_to_stderr() to the presence of an argument, without touching the abort_with_line() call. It's done using an extra if to minimize the diff as it's only temporary. For BUG_ON(), the trace calls are factored before the call to an argument-less ABORT_NOW() since that one will not print the message anymore. --- diff --git a/include/haproxy/bug.h b/include/haproxy/bug.h index 69018d37f..8d7776224 100644 --- a/include/haproxy/bug.h +++ b/include/haproxy/bug.h @@ -303,7 +303,8 @@ static __attribute__((noinline,noreturn,unused)) void abort_with_line(uint line) #define __ABORT_NOW(file, line, ...) do { \ if (sizeof("" __VA_ARGS__) > 1) \ complain(DBG_FATL_ABT, file ":" #line ": " __VA_ARGS__); \ - ha_backtrace_to_stderr(1); \ + if (sizeof("" __VA_ARGS__) > 1) \ + ha_backtrace_to_stderr(1); \ abort_with_line(__LINE__); \ } while (0) @@ -366,10 +367,10 @@ extern __attribute__((__weak__)) struct debug_count __stop_dbg_cnt HA_SECTION_S HA_WEAK(__stop_dbg_cnt); \ if (!_HA_ATOMIC_FETCH_ADD(&__dbg_cnt_##_line.count, 1) || _type != DBG_BUG_ONCE) { \ complain_with_dbg(&__dbg_cnt_##_line); \ + if (_details & (DBG_DET_FAT_FATL|DBG_DET_FAT_WARN)) \ + ha_backtrace_to_stderr(!!(_details & DBG_DET_FAT_FATL)); \ if (_details & DBG_DET_FAT_FATL) \ ABORT_NOW(); \ - else if (_details & DBG_DET_FAT_WARN) \ - ha_backtrace_to_stderr(0); \ } \ } @@ -426,10 +427,10 @@ extern __attribute__((__weak__)) struct debug_count __stop_dbg_cnt HA_SECTION_S ({ static int __match_count_##line; \ !_HA_ATOMIC_FETCH_ADD(&__match_count_##line, 1); })) { \ complain(details, msg); \ + if (details & (DBG_DET_FAT_FATL|DBG_DET_FAT_WARN)) \ + ha_backtrace_to_stderr(!!(details & DBG_DET_FAT_FATL)); \ if (details & DBG_DET_FAT_FATL) \ ABORT_NOW(); \ - else if (details & DBG_DET_FAT_WARN) \ - ha_backtrace_to_stderr(0); \ } \ }