]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: debug: add a new version of complain() that takes a debug_count struct
authorWilly Tarreau <w@1wt.eu>
Tue, 11 Aug 2026 09:21:50 +0000 (11:21 +0200)
committerWilly Tarreau <w@1wt.eu>
Thu, 13 Aug 2026 15:43:30 +0000 (17:43 +0200)
complain_with_dbg() takes a debug_count struct in argument from which
it retrieves everything it needs:
  - details
  - type
  - file name
  - line number
  - description
  - vaargs

This is done by making the common _complain() able to decode such elements
from a debug_count when presented. complain() passes a NULL there and uses
its msg, while complain_with_dbg() passes the debug_count and no msg. This
allows us to get rid of all the pre-made redundant messages and to save
70 kB of code. We're now around 136 kB under the initial size.

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

index 93040ab2f715bdeb50473d0b2a9d00d3364d83e1..69018d37f84d87bf4c8b03a280ca219d487cdf6f 100644 (file)
@@ -169,6 +169,7 @@ struct debug_count {
 
 /* report a bug on stderr */
 void complain(uint details, const char *msg);
+void complain_with_dbg(struct debug_count *dbg);
 void ha_backtrace_to_stderr(int hint);
 
 /* Let's make DEBUG_STRESS equal to zero if not set or not valid, or to
@@ -364,11 +365,7 @@ extern __attribute__((__weak__)) struct debug_count __stop_dbg_cnt  HA_SECTION_S
                HA_WEAK(__start_dbg_cnt);                                       \
                HA_WEAK(__stop_dbg_cnt);                                        \
                if (!_HA_ATOMIC_FETCH_ADD(&__dbg_cnt_##_line.count, 1) || _type != DBG_BUG_ONCE) { \
-                       const char *msg =                                       \
-                               (sizeof("" __VA_ARGS__) > 1) ?                  \
-                                       "\"" #_cond "\" matched at " _file ":" #_line "\x1e" __VA_ARGS__ : \
-                                       "\"" #_cond "\" matched at " _file ":" #_line;  \
-                       complain(_details, msg);                                \
+                       complain_with_dbg(&__dbg_cnt_##_line);                  \
                        if (_details & DBG_DET_FAT_FATL)                        \
                                ABORT_NOW();                                    \
                        else if (_details & DBG_DET_FAT_WARN)                   \
index 56da25d2976d1ac7297deef84b7b19aedaf9a0e4..47546ba5ffec3a0fc143c05bbbd55506cb395225 100644 (file)
@@ -971,11 +971,13 @@ void ha_stuck_warning(void)
  * 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).
+ * used to give extra info to the user about the issue's location). When <dbg>
+ * is non-null, it is used as a source for the message, file, line number, type
+ * etc.
  */
-static void _complain(uint details, const char *msg)
+static void _complain(uint details, const char *msg, struct debug_count *dbg)
 {
-       struct iovec iovec[10];
+       struct iovec iovec[20];
        const char *pfx;
        const char *rs;
        int vec = 0;
@@ -1012,14 +1014,49 @@ static void _complain(uint details, const char *msg)
                vec++;
        }
 
-       /* make rs point either to the RS or to \0 */
-       rs = strchr(msg, '\x1e');
-       if (!rs)
-               rs = msg + strlen(msg);
+       if (dbg) {
+               /* Using only <dbg>. <msg> is ignored and may be NULL.
+                * Make rs point either to the RS or to \0.
+                * Output format: \" <desc> \" " matched at " <file> ":" <line>
+                * (7 fields).
+                */
+               rs = strchr(dbg->desc, '\x1e');
+               if (!rs)
+                       rs = dbg->desc + strlen(dbg->desc);
 
-       iovec[vec].iov_base = (char *)msg;
-       iovec[vec].iov_len  = rs - msg;
-       vec++;
+               iovec[vec].iov_base = "\"";
+               iovec[vec].iov_len  = 1;
+               vec++;
+
+               iovec[vec].iov_base = (char *)dbg->desc;
+               iovec[vec].iov_len  = rs - dbg->desc;
+               vec++;
+
+               iovec[vec].iov_base = "\" matched at ";
+               iovec[vec].iov_len  = strlen(iovec[vec].iov_base);
+               vec++;
+
+               iovec[vec].iov_base = (char *)dbg->file;
+               iovec[vec].iov_len  = strlen(iovec[vec].iov_base);
+               vec++;
+
+               iovec[vec].iov_base = ":";
+               iovec[vec].iov_len  = 1;
+               vec++;
+
+               iovec[vec].iov_base = (char *)ultoa(dbg->line);
+               iovec[vec].iov_len  = strlen(iovec[vec].iov_base);
+               vec++;
+       } else {
+               /* Using the <msg> field. Make rs point either to the RS or to \0 */
+               rs = strchr(msg, '\x1e');
+               if (!rs)
+                       rs = msg + strlen(msg);
+
+               iovec[vec].iov_base = (char *)msg;
+               iovec[vec].iov_len  = rs - msg;
+               vec++;
+       }
 
        /* suffixes may be printed for warning-level */
        if (details & DBG_DET_FAT_WARN) {
@@ -1059,7 +1096,13 @@ static void _complain(uint details, const char *msg)
 /* the exported function */
 void complain(uint details, const char *msg)
 {
-       _complain(details, msg);
+       _complain(details, msg, NULL);
+}
+
+/* the same, for use with a debug_count struct */
+void complain_with_dbg(struct debug_count *dbg)
+{
+       _complain(dbg->details, NULL, dbg);
 }
 
 /* parse a "debug dev exit" command. It always returns 1, though it should never return. */