diff --git a/Makefile b/Makefile index 6b8fa5bca..b87a0af7d 100644 --- a/Makefile +++ b/Makefile @@ -263,7 +263,7 @@ endif # DEBUG_NO_POOLS, DEBUG_FAIL_ALLOC, DEBUG_STRICT_ACTION=[0-3], DEBUG_HPACK, # DEBUG_AUTH, DEBUG_SPOE, DEBUG_UAF, DEBUG_THREAD, DEBUG_STRICT, DEBUG_DEV, # DEBUG_TASK, DEBUG_MEMORY_POOLS, DEBUG_POOL_TRACING, DEBUG_QPACK, DEBUG_LIST, -# DEBUG_COUNTERS=[0-1], DEBUG_STRESS, DEBUG_UNIT. +# DEBUG_COUNTERS=[0-2], DEBUG_STRESS, DEBUG_UNIT. DEBUG = #### Trace options diff --git a/doc/configuration.txt b/doc/configuration.txt index f5e98cb38..9b4636a64 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -1741,6 +1741,7 @@ The following keywords are supported in the "global" section : * Debugging - anonkey + - debug.counters - force-cfg-parser-pause - quiet - warn-blocked-traffic-after @@ -4815,6 +4816,19 @@ anonkey from the CLI command "set anon global-key". See also command line argument "-dC" in the management manual. +debug.counters { on | off } + Enables ('on') or disables ('off') the updating of event counters in the + code. These are the counters reported under the type "CNT" in the CLI command + "debug counters". These counters are only available when the code was build + with DEBUG_COUNTERS set to a value 1 or above. With the value 1, the counters + are not updated by default ("debug.counters off"), and with value 2, they are + updated by default ("debug.counters on"). There is normally no reason to + change this setting unless a developer requests it, or unless it is suspected + to consume abnormal amounts of CPU (in which case a report to developers is + necessary with a dump of the counters). It is also possible to change this + status at run time using the "debug counters" CLI command. Please consult the + management manual. + force-cfg-parser-pause This command is pausing the configuration parser for milliseconds. This is useful for development or for testing timeouts of init scripts, diff --git a/doc/management.txt b/doc/management.txt index 191c0c499..246368500 100644 --- a/doc/management.txt +++ b/doc/management.txt @@ -1999,7 +1999,7 @@ commit ssl crl-file See also "new ssl crl-file", "set ssl crl-file", "abort ssl crl-file" and "add ssl crt-list". -debug counters [reset|show|all|bug|chk|cnt|glt|?]* +debug counters [reset|show|on|off|all|bug|chk|cnt|glt|?]* List internal counters placed in the code, which may vary depending on some build options. Some of them depend on DEBUG_STRICT, others on DEBUG_COUNTERS. The command takes a combination of multiple arguments, some defining actions @@ -2009,6 +2009,8 @@ debug counters [reset|show|all|bug|chk|cnt|glt|?]* - chk enables listing the counters for CHECK_IF() statements - glt enables listing the counters for COUNT_GLITCH() statements - all enables showing counters that never triggered (value 0) + - off action: disables updating of the COUNT_IF() counters + - on action: enables updating of the COUNT_IF() counters - reset action: resets all specified counters - show action: shows all specified counters diff --git a/include/haproxy/bug.h b/include/haproxy/bug.h index f583e093d..71d302e87 100644 --- a/include/haproxy/bug.h +++ b/include/haproxy/bug.h @@ -161,6 +161,8 @@ static __attribute__((noinline,noreturn,unused)) void abort_with_line(uint line) * COUNT_IF() invocation requires a special section ("dbg_cnt") hence a modern * linker. */ +extern unsigned int debug_enable_counters; + #if !defined(USE_OBSOLETE_LINKER) /* type of checks that can be verified. We cannot really distinguish between @@ -225,17 +227,21 @@ extern __attribute__((__weak__)) struct debug_count __stop_dbg_cnt HA_SECTION_S /* Matrix for DEBUG_COUNTERS: * 0 : only BUG_ON() and CHECK_IF() are reported (super rare) - * 1 : COUNT_GLITCH() and COUNT_IF() are also reported (rare) + * 1 : COUNT_GLITCH() are also reported (rare) + * COUNT_IF() are also reported only if debug_enable_counters was set + * 2 : COUNT_IF() are also reported unless debug_enable_counters was reset */ /* Core of the COUNT_IF() macro, checks the condition and counts one hit if - * true. It's only enabled at DEBUG_COUNTERS >= 1. + * true. It's only enabled at DEBUG_COUNTERS >= 1, and enabled by default if + * DEBUG_COUNTERS >= 2. */ # if defined(DEBUG_COUNTERS) && (DEBUG_COUNTERS >= 1) -# define _COUNT_IF(cond, file, line, ...) \ - (unlikely(cond) ? ({ \ - __DBG_COUNT(cond, file, line, DBG_COUNT_IF, __VA_ARGS__); \ - 1; /* let's return the true condition */ \ +# define _COUNT_IF(cond, file, line, ...) \ + (unlikely(cond) ? ({ \ + if (debug_enable_counters) \ + __DBG_COUNT(cond, file, line, DBG_COUNT_IF, __VA_ARGS__); \ + 1; /* let's return the true condition */ \ }) : 0) # else # define _COUNT_IF(cond, file, line, ...) DISGUISE(unlikely(cond) ? 1 : 0) diff --git a/src/debug.c b/src/debug.c index d3229e6b9..ebf79cb7b 100644 --- a/src/debug.c +++ b/src/debug.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -163,6 +164,7 @@ struct post_mortem { unsigned int debug_commands_issued = 0; unsigned int warn_blocked_issued = 0; +unsigned int debug_enable_counters = (DEBUG_COUNTERS >= 2); /* dumps a backtrace of the current thread that is appended to buffer . * Lines are prefixed with the string which may be empty (used for @@ -2254,6 +2256,14 @@ static int debug_parse_cli_counters(char **args, char *payload, struct appctx *a action = 1; continue; } + else if (strcmp(args[arg], "off") == 0) { + action = 2; + continue; + } + else if (strcmp(args[arg], "on") == 0) { + action = 3; + continue; + } else if (strcmp(args[arg], "all") == 0) { ctx->show_all = 1; continue; @@ -2279,7 +2289,7 @@ static int debug_parse_cli_counters(char **args, char *payload, struct appctx *a continue; } else - return cli_err(appctx, "Expects an optional action ('reset','show'), optional types ('bug','chk','cnt','glt') and optionally 'all' to even dump null counters.\n"); + return cli_err(appctx, "Expects an optional action ('reset','show','on','off'), optional types ('bug','chk','cnt','glt') and optionally 'all' to even dump null counters.\n"); } #if (DEBUG_STRICT > 0) || (DEBUG_COUNTERS > 0) @@ -2299,6 +2309,12 @@ static int debug_parse_cli_counters(char **args, char *payload, struct appctx *a } return 1; } + else if (action == 2 || action == 3) { // off/on + if (!cli_has_level(appctx, ACCESS_LVL_ADMIN)) + return 1; + HA_ATOMIC_STORE(&debug_enable_counters, action == 3); + return 0; + } /* OK it's a show, let's dump relevant counters */ return 0; @@ -2340,10 +2356,11 @@ static int debug_iohandler_counters(struct appctx *appctx) } if (ptr->type < DBG_COUNTER_TYPES) - chunk_appendf(&trash, "%-10u %3s %s:%d %s()%s%s\n", + chunk_appendf(&trash, "%-10u %3s %s:%d %s()%s%s%s\n", ptr->count, bug_type[ptr->type], name, ptr->line, ptr->func, - *ptr->desc ? ": " : "", ptr->desc); + *ptr->desc ? ": " : "", ptr->desc, + (ptr->type == DBG_COUNT_IF && !debug_enable_counters) ? " (stopped)" : ""); if (applet_putchk(appctx, &trash) == -1) { ctx->start = ptr; @@ -2807,6 +2824,36 @@ void list_unittests() #endif +#if DEBUG_STRICT > 1 +/* config parser for global "debug.counters", accepts "on" or "off" */ +static int cfg_parse_debug_counters(char **args, int section_type, struct proxy *curpx, + const struct proxy *defpx, const char *file, int line, + char **err) +{ + if (too_many_args(1, args, err, NULL)) + return -1; + + if (strcmp(args[1], "on") == 0) { + HA_ATOMIC_STORE(&debug_enable_counters, 1); + } + else if (strcmp(args[1], "off") == 0) + HA_ATOMIC_STORE(&debug_enable_counters, 0); + else { + memprintf(err, "'%s' expects either 'on' or 'off' but got '%s'.", args[0], args[1]); + return -1; + } + return 0; +} +#endif + +/* config keyword parsers */ +static struct cfg_kw_list cfg_kws = {ILH, { +#if DEBUG_STRICT > 1 + { CFG_GLOBAL, "debug.counters", cfg_parse_debug_counters }, +#endif + { 0, NULL, NULL } +}}; +INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws); /* register cli keywords */ static struct cli_kw_list cli_kws = {{ },{