]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: debug: make the complain() function print the suffix
authorWilly Tarreau <w@1wt.eu>
Mon, 10 Aug 2026 16:44:41 +0000 (18:44 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 13 Aug 2026 15:43:30 +0000 (17:43 +0200)
The suffix, such as "please contact the developer" that is printed on
each warning, with its optional variant "not crashing ..." can be entirely
computed by complain() based on the flags description. This way we can drop
that from the macros and further shrink the messages.

The code size reduced by 6.5 kB.

include/haproxy/bug.h
src/debug.c

index 8844feca2b7bbbaf0eea97fcff02fb653ebc2031..c506ee7e00b3f7d5ab48911765ce9393fd3c7efe 100644 (file)
@@ -393,7 +393,7 @@ extern __attribute__((__weak__)) struct debug_count __stop_dbg_cnt  HA_SECTION_S
 #define COUNT_GLITCH(...) _COUNT_GLITCH(__FILE__, __LINE__, __VA_ARGS__)
 
 /* This is the generic low-level macro dealing with conditional warnings and
- * bugs. The caller decides whether to crash or not and what suffix to pass.
+ * bugs. The caller decides whether to crash or not.
  * The macro returns the boolean value of the condition as an int for the case
  * where it wouldn't die. The <details> flag is made of:
  *  - details & DBG_DET_FAT_FATL: crash yes/no;
@@ -402,19 +402,19 @@ extern __attribute__((__weak__)) struct debug_count __stop_dbg_cnt  HA_SECTION_S
  * on a second line after the condition message, to give a bit more context
  * about the problem.
  */
-#define _BUG_ON(cond, file, line, details, sfx, ...)                           \
+#define _BUG_ON(cond, file, line, details, ...)                                        \
        (void)(unlikely(cond) ? ({                                              \
                __DBG_COUNT(cond, file, line, DBG_BUG, __VA_ARGS__);            \
-               __BUG_ON(cond, file, line, details, sfx, __VA_ARGS__);          \
+               __BUG_ON(cond, file, line, details, __VA_ARGS__);               \
                1; /* let's return the true condition */                        \
        }) : 0)
 
-#define __BUG_ON(cond, file, line, details, sfx, ...) do {             \
+#define __BUG_ON(cond, file, line, details, ...) do {                  \
                const char *msg;                                        \
                if (sizeof("" __VA_ARGS__) > 1)                         \
-                       msg = "\"" #cond "\" matched at " file ":" #line "" sfx "\x1e" __VA_ARGS__; \
+                       msg = "\"" #cond "\" matched at " file ":" #line "\x1e" __VA_ARGS__; \
                else                                                    \
-                       msg = "\"" #cond "\" matched at " file ":" #line "" sfx; \
+                       msg = "\"" #cond "\" matched at " file ":" #line; \
                complain(details, msg);                                 \
                if (details & DBG_DET_FAT_FATL)                         \
                        ABORT_NOW();                                    \
@@ -427,20 +427,20 @@ extern __attribute__((__weak__)) struct debug_count __stop_dbg_cnt  HA_SECTION_S
  * certain unexpected conditions in field. Later on, in cores it will be
  * possible to verify these counters.
  */
-#define _BUG_ON_ONCE(cond, file, line, details, sfx, ...)                      \
+#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, details, sfx, __VA_ARGS__);     \
+               __BUG_ON_ONCE(cond, file, line, details, __VA_ARGS__);          \
                1; /* let's return the true condition */                        \
        }) : 0)
 
-#define __BUG_ON_ONCE(cond, file, line, details, sfx, ...) do {                \
+#define __BUG_ON_ONCE(cond, file, line, details, ...) do {             \
                static int __match_count_##line;                        \
                const char *msg;                                        \
                if (sizeof("" __VA_ARGS__) > 1)                         \
-                       msg = "\"" #cond "\" matched at " file ":" #line "" sfx "\x1e" __VA_ARGS__; \
+                       msg = "\"" #cond "\" matched at " file ":" #line "\x1e" __VA_ARGS__; \
                else                                                    \
-                       msg = "\"" #cond "\" matched at " file ":" #line "" sfx; \
+                       msg = "\"" #cond "\" matched at " file ":" #line; \
                if (_HA_ATOMIC_FETCH_ADD(&__match_count_##line, 1))     \
                        break;                                          \
                complain(details, msg);                                 \
@@ -466,27 +466,27 @@ extern __attribute__((__weak__)) struct debug_count __stop_dbg_cnt  HA_SECTION_S
 #if defined(DEBUG_STRICT) && (DEBUG_STRICT > 0)
 # if defined(DEBUG_STRICT_ACTION) && (DEBUG_STRICT_ACTION < 1)
 /* Lowest level: BUG_ON() warns, WARN_ON() warns, CHECK_IF() warns */
-#  define BUG_ON(cond, ...)   _BUG_ON     (cond, __FILE__, __LINE__, DBG_WARN_BUG,   " (not crashing but process is untrusted now, please report to developers)", __VA_ARGS__)
-#  define WARN_ON(cond, ...)  _BUG_ON     (cond, __FILE__, __LINE__, DBG_WARN_WRN,  " (please report to developers)", __VA_ARGS__)
-#  define CHECK_IF(cond, ...) _BUG_ON_ONCE(cond, __FILE__, __LINE__, DBG_WARN_CHK, " (please report to developers)", __VA_ARGS__)
+#  define BUG_ON(cond, ...)   _BUG_ON     (cond, __FILE__, __LINE__, DBG_WARN_BUG, __VA_ARGS__)
+#  define WARN_ON(cond, ...)  _BUG_ON     (cond, __FILE__, __LINE__, DBG_WARN_WRN, __VA_ARGS__)
+#  define CHECK_IF(cond, ...) _BUG_ON_ONCE(cond, __FILE__, __LINE__, DBG_WARN_CHK, __VA_ARGS__)
 #  define COUNT_IF(cond, ...) _COUNT_IF   (cond, __FILE__, __LINE__, __VA_ARGS__)
 # elif !defined(DEBUG_STRICT_ACTION) || (DEBUG_STRICT_ACTION == 1)
 /* default level: BUG_ON() crashes, WARN_ON() warns, CHECK_IF() warns */
-#  define BUG_ON(cond, ...)   _BUG_ON     (cond, __FILE__, __LINE__, DBG_FATL_BUG,     "", __VA_ARGS__)
-#  define WARN_ON(cond, ...)  _BUG_ON     (cond, __FILE__, __LINE__, DBG_WARN_WRN,  " (please report to developers)", __VA_ARGS__)
-#  define CHECK_IF(cond, ...) _BUG_ON_ONCE(cond, __FILE__, __LINE__, DBG_WARN_CHK, " (please report to developers)", __VA_ARGS__)
+#  define BUG_ON(cond, ...)   _BUG_ON     (cond, __FILE__, __LINE__, DBG_FATL_BUG, __VA_ARGS__)
+#  define WARN_ON(cond, ...)  _BUG_ON     (cond, __FILE__, __LINE__, DBG_WARN_WRN, __VA_ARGS__)
+#  define CHECK_IF(cond, ...) _BUG_ON_ONCE(cond, __FILE__, __LINE__, DBG_WARN_CHK, __VA_ARGS__)
 #  define COUNT_IF(cond, ...) _COUNT_IF   (cond, __FILE__, __LINE__, __VA_ARGS__)
 # elif defined(DEBUG_STRICT_ACTION) && (DEBUG_STRICT_ACTION == 2)
 /* Stricter level: BUG_ON() crashes, WARN_ON() crashes, CHECK_IF() warns */
-#  define BUG_ON(cond, ...)   _BUG_ON     (cond, __FILE__, __LINE__, DBG_FATL_BUG,     "", __VA_ARGS__)
-#  define WARN_ON(cond, ...)  _BUG_ON     (cond, __FILE__, __LINE__, DBG_FATL_WRN,    "", __VA_ARGS__)
-#  define CHECK_IF(cond, ...) _BUG_ON_ONCE(cond, __FILE__, __LINE__, DBG_WARN_CHK, " (please report to developers)", __VA_ARGS__)
+#  define BUG_ON(cond, ...)   _BUG_ON     (cond, __FILE__, __LINE__, DBG_FATL_BUG, __VA_ARGS__)
+#  define WARN_ON(cond, ...)  _BUG_ON     (cond, __FILE__, __LINE__, DBG_FATL_WRN, __VA_ARGS__)
+#  define CHECK_IF(cond, ...) _BUG_ON_ONCE(cond, __FILE__, __LINE__, DBG_WARN_CHK, __VA_ARGS__)
 #  define COUNT_IF(cond, ...) _COUNT_IF   (cond, __FILE__, __LINE__, __VA_ARGS__)
 # elif defined(DEBUG_STRICT_ACTION) && (DEBUG_STRICT_ACTION >= 3)
 /* Developer/CI level: BUG_ON() crashes, WARN_ON() crashes, CHECK_IF() crashes */
-#  define BUG_ON(cond, ...)   _BUG_ON     (cond, __FILE__, __LINE__, DBG_FATL_BUG,     "", __VA_ARGS__)
-#  define WARN_ON(cond, ...)  _BUG_ON     (cond, __FILE__, __LINE__, DBG_FATL_WRN,    "", __VA_ARGS__)
-#  define CHECK_IF(cond, ...) _BUG_ON_ONCE(cond, __FILE__, __LINE__, DBG_FATL_CHK,   "", __VA_ARGS__)
+#  define BUG_ON(cond, ...)   _BUG_ON     (cond, __FILE__, __LINE__, DBG_FATL_BUG, __VA_ARGS__)
+#  define WARN_ON(cond, ...)  _BUG_ON     (cond, __FILE__, __LINE__, DBG_FATL_WRN, __VA_ARGS__)
+#  define CHECK_IF(cond, ...) _BUG_ON_ONCE(cond, __FILE__, __LINE__, DBG_FATL_CHK, __VA_ARGS__)
 #  define COUNT_IF(cond, ...) _COUNT_IF   (cond, __FILE__, __LINE__, __VA_ARGS__)
 # endif
 #else /* DEBUG_STRICT not defined below */
@@ -509,18 +509,18 @@ extern __attribute__((__weak__)) struct debug_count __stop_dbg_cnt  HA_SECTION_S
 #if defined(DEBUG_STRICT) && (DEBUG_STRICT > 1)
 # if defined(DEBUG_STRICT_ACTION) && (DEBUG_STRICT_ACTION < 1)
 /* Lowest level: BUG_ON() warns, CHECK_IF() warns */
-#  define BUG_ON_HOT(cond, ...)   _BUG_ON_ONCE(cond, __FILE__, __LINE__, DBG_WARN_BUG,   " (not crashing but process is untrusted now, please report to developers)", __VA_ARGS__)
-#  define CHECK_IF_HOT(cond, ...) _BUG_ON_ONCE(cond, __FILE__, __LINE__, DBG_WARN_CHK, " (please report to developers)", __VA_ARGS__)
+#  define BUG_ON_HOT(cond, ...)   _BUG_ON_ONCE(cond, __FILE__, __LINE__, DBG_WARN_BUG, __VA_ARGS__)
+#  define CHECK_IF_HOT(cond, ...) _BUG_ON_ONCE(cond, __FILE__, __LINE__, DBG_WARN_CHK, __VA_ARGS__)
 #  define COUNT_IF_HOT(cond, ...) _COUNT_IF   (cond, __FILE__, __LINE__, __VA_ARGS__)
 # elif !defined(DEBUG_STRICT_ACTION) || (DEBUG_STRICT_ACTION < 3)
 /* default level: BUG_ON() crashes, CHECK_IF() warns */
-#  define BUG_ON_HOT(cond, ...)   _BUG_ON     (cond, __FILE__, __LINE__, DBG_FATL_BUG,     "", __VA_ARGS__)
-#  define CHECK_IF_HOT(cond, ...) _BUG_ON_ONCE(cond, __FILE__, __LINE__, DBG_WARN_CHK, " (please report to developers)", __VA_ARGS__)
+#  define BUG_ON_HOT(cond, ...)   _BUG_ON     (cond, __FILE__, __LINE__, DBG_FATL_BUG, __VA_ARGS__)
+#  define CHECK_IF_HOT(cond, ...) _BUG_ON_ONCE(cond, __FILE__, __LINE__, DBG_WARN_CHK, __VA_ARGS__)
 #  define COUNT_IF_HOT(cond, ...) _COUNT_IF   (cond, __FILE__, __LINE__, __VA_ARGS__)
 # elif defined(DEBUG_STRICT_ACTION) && (DEBUG_STRICT_ACTION >= 3)
 /* Developer/CI level: BUG_ON() crashes, CHECK_IF() crashes */
-#  define BUG_ON_HOT(cond, ...)   _BUG_ON     (cond, __FILE__, __LINE__, DBG_FATL_BUG,     "", __VA_ARGS__)
-#  define CHECK_IF_HOT(cond, ...) _BUG_ON_ONCE(cond, __FILE__, __LINE__, DBG_FATL_CHK,   "", __VA_ARGS__)
+#  define BUG_ON_HOT(cond, ...)   _BUG_ON     (cond, __FILE__, __LINE__, DBG_FATL_BUG, __VA_ARGS__)
+#  define CHECK_IF_HOT(cond, ...) _BUG_ON_ONCE(cond, __FILE__, __LINE__, DBG_FATL_CHK, __VA_ARGS__)
 #  define COUNT_IF_HOT(cond, ...) _COUNT_IF   (cond, __FILE__, __LINE__, __VA_ARGS__)
 # endif
 #else /* DEBUG_STRICT <= 1 below */
index f107fa783bfda39f444fe1ae3e1240fd9eeaabba..f49c94e0088023ab770997dd44562e349e6892eb 100644 (file)
@@ -967,9 +967,9 @@ void ha_stuck_warning(void)
 
 /* Complain with message <msg> on stderr with a '\n' at the begin and at the
  * end. Depending on the fatality, and type of the event in <details>, a
- * different prefix will be appended. Then the event type may result in some
- * taining of the process to happen. If the string contains an RS char (\x1e)
- * then it's used as a delimiter: the main message stops there, and what
+ * different prefix and suffix will be appended. Then the event type may result
+ * in some taining of the process to happen. If the string contains an RS char
+ * (\x1e) then it's used as a delimiter: the main message stops there, and what
  * follows is a new line that will be appended after another LF (normally it's
  * used to give extra info to the user about the issue's location).
  */
@@ -1021,6 +1021,18 @@ void complain(uint details, const char *msg)
        iovec[vec].iov_len  = rs - msg;
        vec++;
 
+       /* suffixes may be printed for warning-level */
+       if (details & DBG_DET_FAT_WARN) {
+               pfx = NULL;
+               if (details & DBG_DET_TYP_BUG)
+                       pfx = " (not crashing but process is untrusted now, please report to developers)";
+               else
+                       pfx = " (please report to developers)";
+               iovec[vec].iov_base = (char *)pfx;
+               iovec[vec].iov_len  = strlen(pfx);
+               vec++;
+       }
+
        if (*rs) {
                /* there's an extra string */
                iovec[vec].iov_base = "\n";