From: Willy Tarreau Date: Mon, 10 Aug 2026 18:07:01 +0000 (+0200) Subject: MINOR: debug: unify __BUG_ON() and __BUG_ON_ONCE() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5960fe1d8e88b1af8cc46aeefcdb86c78b08b070;p=thirdparty%2Fhaproxy.git MINOR: debug: unify __BUG_ON() and __BUG_ON_ONCE() We can do that thanks to the debug type. The line counter moved into an if () block conditioned by the type so it continues to emit nothing for regular bugs. Surprizingly, the code grew by 1 kB. It's apparently caused by having an impossible "if" statement containing a "break". Splitting the macro in two to put the BUG_ON_ONCE() callers aside showed that having only "if (0) break;" in the block was sufficient to make gcc deoptimize it and result in this same growth. This was observed with 9.5. Let's consider this a temporary limitation and keep it this way. --- diff --git a/include/haproxy/bug.h b/include/haproxy/bug.h index dcfeea58b..efabaab5f 100644 --- a/include/haproxy/bug.h +++ b/include/haproxy/bug.h @@ -409,12 +409,18 @@ extern __attribute__((__weak__)) struct debug_count __stop_dbg_cnt HA_SECTION_S 1; /* let's return the true condition */ \ }) : 0) +/* This is called by _BUG_ON() and _BUG_ON_ONCE() to handle the event. */ #define __BUG_ON(cond, file, line, type, details, ...) do { \ const char *msg; \ if (sizeof("" __VA_ARGS__) > 1) \ msg = "\"" #cond "\" matched at " file ":" #line "\x1e" __VA_ARGS__; \ else \ msg = "\"" #cond "\" matched at " file ":" #line; \ + if (type == DBG_BUG_ONCE) { \ + static int __match_count_##line; \ + if (_HA_ATOMIC_FETCH_ADD(&__match_count_##line, 1)) \ + break; \ + } \ complain(details, msg); \ if (details & DBG_DET_FAT_FATL) \ ABORT_NOW(); \ @@ -430,27 +436,10 @@ extern __attribute__((__weak__)) struct debug_count __stop_dbg_cnt HA_SECTION_S #define _BUG_ON_ONCE(cond, file, line, details, ...) \ (void)(unlikely(cond) ? ({ \ __DBG_COUNT(cond, file, line, DBG_BUG_ONCE, __VA_ARGS__); \ - __BUG_ON_ONCE(cond, file, line, DBG_BUG_ONCE, details, __VA_ARGS__); \ + __BUG_ON(cond, file, line, DBG_BUG_ONCE, details, __VA_ARGS__); \ 1; /* let's return the true condition */ \ }) : 0) -#define __BUG_ON_ONCE(cond, file, line, type, details, ...) do { \ - static int __match_count_##line; \ - const char *msg; \ - if (sizeof("" __VA_ARGS__) > 1) \ - msg = "\"" #cond "\" matched at " file ":" #line "\x1e" __VA_ARGS__; \ - else \ - msg = "\"" #cond "\" matched at " file ":" #line; \ - if (_HA_ATOMIC_FETCH_ADD(&__match_count_##line, 1)) \ - break; \ - complain(details, msg); \ - if (details & DBG_DET_FAT_FATL) \ - ABORT_NOW(); \ - else if (details & DBG_DET_FAT_WARN) \ - ha_backtrace_to_stderr(0); \ - } while (0) - - /* DEBUG_STRICT enables/disables runtime checks on condition * DEBUG_STRICT_ACTION indicates the level of verification on the rules when * is true: