MEDIUM: debug: now always print a backtrace on CRASH_NOW() and friends
The purpose is to enable the dumping of a backtrace on BUG_ON(). While it's very useful to know that a condition was met, very often some caller context is missing to figure how the condition could happen. From now on, on systems featuring backtrace, a backtrace of the calling thread will also be dumped to stderr in addition to the unexpected condition. This will help users of DEBUG_STRICT as they'll most often find this backtrace in their logs even if they can't find their core file. A new "debug dev bug" expert-mode CLI command was added to test the feature.
This commit is contained in:
parent
a8459b28c3
commit
5baf4fe31a
@ -39,12 +39,12 @@
|
||||
|
||||
#ifdef DEBUG_USE_ABORT
|
||||
/* abort() is better recognized by code analysis tools */
|
||||
#define ABORT_NOW() abort()
|
||||
#define ABORT_NOW() do { extern void ha_backtrace_to_stderr(); ha_backtrace_to_stderr(); abort(); } while (0)
|
||||
#else
|
||||
/* More efficient than abort() because it does not mangle the
|
||||
* stack and stops at the exact location we need.
|
||||
*/
|
||||
#define ABORT_NOW() (*(volatile int*)1=0)
|
||||
#define ABORT_NOW() do { extern void ha_backtrace_to_stderr(); ha_backtrace_to_stderr(); (*(volatile int*)1=0); } while (0)
|
||||
#endif
|
||||
|
||||
/* BUG_ON: complains if <cond> is true when DEBUG_STRICT or DEBUG_STRICT_NOCRASH
|
||||
@ -55,7 +55,7 @@
|
||||
#if defined(DEBUG_STRICT)
|
||||
#define CRASH_NOW() ABORT_NOW()
|
||||
#else
|
||||
#define CRASH_NOW()
|
||||
#define CRASH_NOW() do { ha_backtrace_to_stderr(); } while (0)
|
||||
#endif
|
||||
|
||||
#define BUG_ON(cond) _BUG_ON(cond, __FILE__, __LINE__)
|
||||
|
14
src/debug.c
14
src/debug.c
@ -322,6 +322,19 @@ static int debug_parse_cli_exit(char **args, char *payload, struct appctx *appct
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* parse a "debug dev bug" command. It always returns 1, though it should never return.
|
||||
* Note: we make sure not to make the function static so that it appears in the trace.
|
||||
*/
|
||||
int debug_parse_cli_bug(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
|
||||
return 1;
|
||||
|
||||
_HA_ATOMIC_ADD(&debug_commands_issued, 1);
|
||||
BUG_ON(one > zero);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* parse a "debug dev close" command. It always returns 1. */
|
||||
static int debug_parse_cli_close(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
@ -1144,6 +1157,7 @@ REGISTER_PER_THREAD_INIT(init_debug_per_thread);
|
||||
|
||||
/* register cli keywords */
|
||||
static struct cli_kw_list cli_kws = {{ },{
|
||||
{{ "debug", "dev", "bug", NULL }, "debug dev bug : call BUG_ON()", debug_parse_cli_bug, NULL, NULL, NULL, ACCESS_EXPERT },
|
||||
{{ "debug", "dev", "close", NULL }, "debug dev close <fd> : close this file descriptor", debug_parse_cli_close, NULL, NULL, NULL, ACCESS_EXPERT },
|
||||
{{ "debug", "dev", "delay", NULL }, "debug dev delay [ms] : sleep this long", debug_parse_cli_delay, NULL, NULL, NULL, ACCESS_EXPERT },
|
||||
#if defined(DEBUG_DEV)
|
||||
|
Loading…
x
Reference in New Issue
Block a user