diff options
Diffstat (limited to 'src/debug.c')
-rw-r--r-- | src/debug.c | 138 |
1 files changed, 114 insertions, 24 deletions
diff --git a/src/debug.c b/src/debug.c index 756c194..5f21f02 100644 --- a/src/debug.c +++ b/src/debug.c @@ -46,6 +46,7 @@ #include <haproxy/thread.h> #include <haproxy/time.h> #include <haproxy/tools.h> +#include <haproxy/trace.h> #include <import/ist.h> @@ -112,7 +113,7 @@ struct post_mortem { uid_t boot_uid; gid_t boot_gid; struct rlimit limit_fd; // RLIMIT_NOFILE - struct rlimit limit_ram; // RLIMIT_AS or RLIMIT_DATA + struct rlimit limit_ram; // RLIMIT_DATA #if defined(USE_THREAD) struct { @@ -456,13 +457,8 @@ void ha_task_dump(struct buffer *buf, const struct task *task, const char *pfx) */ static int cli_io_handler_show_threads(struct appctx *appctx) { - struct stconn *sc = appctx_sc(appctx); int thr; - /* FIXME: Don't watch the other side !*/ - if (unlikely(sc_opposite(sc)->flags & SC_FL_SHUT_DONE)) - return 1; - if (appctx->st0) thr = appctx->st1; else @@ -666,7 +662,7 @@ int debug_parse_cli_bug(char **args, char *payload, struct appctx *appctx, void return 1; _HA_ATOMIC_INC(&debug_commands_issued); - BUG_ON(one > zero); + BUG_ON(one > zero, "This was triggered on purpose from the CLI 'debug dev bug' command."); return 1; } @@ -679,7 +675,7 @@ int debug_parse_cli_warn(char **args, char *payload, struct appctx *appctx, void return 1; _HA_ATOMIC_INC(&debug_commands_issued); - WARN_ON(one > zero); + WARN_ON(one > zero, "This was triggered on purpose from the CLI 'debug dev warn' command."); return 1; } @@ -692,7 +688,7 @@ int debug_parse_cli_check(char **args, char *payload, struct appctx *appctx, voi return 1; _HA_ATOMIC_INC(&debug_commands_issued); - CHECK_IF(one > zero); + CHECK_IF(one > zero, "This was triggered on purpose from the CLI 'debug dev check' command."); return 1; } @@ -1504,6 +1500,112 @@ static int debug_parse_cli_sched(char **args, char *payload, struct appctx *appc return cli_err(appctx, "Not enough memory"); } +#if defined(DEBUG_DEV) +/* All of this is for "trace dbg" */ + +static struct trace_source trace_dbg __read_mostly = { + .name = IST("dbg"), + .desc = "trace debugger", + .report_events = ~0, // report everything by default +}; + +#define TRACE_SOURCE &trace_dbg +INITCALL1(STG_REGISTER, trace_register_source, TRACE_SOURCE); + +/* This is the task handler used to send traces in loops. Note that the task's + * context contains the number of remaining calls to be done. The task sends 20 + * messages per wakeup. + */ +static struct task *debug_trace_task(struct task *t, void *ctx, unsigned int state) +{ + ulong count; + + /* send 2 traces enter/leave +18 devel = 20 traces total */ + TRACE_ENTER(1); + TRACE_DEVEL("msg01 has 20 bytes .", 1); + TRACE_DEVEL("msg02 has 20 bytes .", 1); + TRACE_DEVEL("msg03 has 20 bytes .", 1); + TRACE_DEVEL("msg04 has 70 bytes payload: 0123456789 0123456789 0123456789 012345678", 1); + TRACE_DEVEL("msg05 has 70 bytes payload: 0123456789 0123456789 0123456789 012345678", 1); + TRACE_DEVEL("msg06 has 70 bytes payload: 0123456789 0123456789 0123456789 012345678", 1); + TRACE_DEVEL("msg07 has 120 bytes payload: 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 012", 1); + TRACE_DEVEL("msg08 has 120 bytes payload: 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 012", 1); + TRACE_DEVEL("msg09 has 120 bytes payload: 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 012", 1); + TRACE_DEVEL("msg10 has 170 bytes payload: 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 012345678", 1); + TRACE_DEVEL("msg11 has 170 bytes payload: 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 012345678", 1); + TRACE_DEVEL("msg12 has 170 bytes payload: 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 012345678", 1); + TRACE_DEVEL("msg13 has 220 bytes payload: 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123", 1); + TRACE_DEVEL("msg14 has 220 bytes payload: 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123", 1); + TRACE_DEVEL("msg15 has 220 bytes payload: 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123", 1); + TRACE_DEVEL("msg16 has 270 bytes payload: 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789", 1); + TRACE_DEVEL("msg17 has 270 bytes payload: 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789", 1); + TRACE_DEVEL("msg18 has 270 bytes payload: 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789", 1); + TRACE_LEAVE(1); + + count = (ulong)t->context; + t->context = (void*)count - 1; + + if (count) + task_wakeup(t, TASK_WOKEN_MSG); + else { + task_destroy(t); + t = NULL; + } + return t; +} + +/* parse a "debug dev trace" command + * debug dev trace <nbthr>. + * It will create as many tasks (one per thread), starting from lowest threads. + * The traces will stop after 1M wakeups or 20M messages ~= 4GB of data. + */ +static int debug_parse_cli_trace(char **args, char *payload, struct appctx *appctx, void *private) +{ + unsigned long count = 1; + unsigned long i; + char *msg = NULL; + char *endarg; + + if (!cli_has_level(appctx, ACCESS_LVL_ADMIN)) + return 1; + + _HA_ATOMIC_INC(&debug_commands_issued); + + if (!args[3][0]) { + memprintf(&msg, "Need a thread count. Note that 20M msg will be sent per thread.\n"); + goto fail; + } + + /* parse the new value . */ + count = strtoll(args[3], &endarg, 0); + if (args[3][1] && *endarg) { + memprintf(&msg, "Ignoring unparsable thread number '%s'.\n", args[3]); + goto fail; + } + + if (count >= global.nbthread) + count = global.nbthread; + + for (i = 0; i < count; i++) { + struct task *task = task_new_on(i); + + if (!task) + goto fail; + + task->process = debug_trace_task; + task->context = (void*)(ulong)1000000; // 1M wakeups = 20M messages + task_wakeup(task, TASK_WOKEN_INIT); + } + + if (msg && *msg) + return cli_dynmsg(appctx, LOG_INFO, msg); + return 1; + + fail: + return cli_dynmsg(appctx, LOG_ERR, msg); +} +#endif /* DEBUG_DEV */ + /* CLI state for "debug dev fd" */ struct dev_fd_ctx { int start_fd; @@ -1531,7 +1633,6 @@ static int debug_parse_cli_fd(char **args, char *payload, struct appctx *appctx, static int debug_iohandler_fd(struct appctx *appctx) { struct dev_fd_ctx *ctx = appctx->svcctx; - struct stconn *sc = appctx_sc(appctx); struct sockaddr_storage sa; struct stat statbuf; socklen_t salen, vlen; @@ -1540,10 +1641,6 @@ static int debug_iohandler_fd(struct appctx *appctx) int ret = 1; int i, fd; - /* FIXME: Don't watch the other side !*/ - if (unlikely(sc_opposite(sc)->flags & SC_FL_SHUT_DONE)) - goto end; - chunk_reset(&trash); thread_isolate(); @@ -1693,7 +1790,6 @@ static int debug_iohandler_fd(struct appctx *appctx) } thread_release(); - end: return ret; } @@ -1763,15 +1859,10 @@ static int debug_parse_cli_memstats(char **args, char *payload, struct appctx *a static int debug_iohandler_memstats(struct appctx *appctx) { struct dev_mem_ctx *ctx = appctx->svcctx; - struct stconn *sc = appctx_sc(appctx); struct mem_stats *ptr; const char *pfx = ctx->match; int ret = 1; - /* FIXME: Don't watch the other side !*/ - if (unlikely(sc_opposite(sc)->flags & SC_FL_SHUT_DONE)) - goto end; - if (!ctx->width) { /* we don't know the first column's width, let's compute it * now based on a first pass on printable entries and their @@ -2182,11 +2273,7 @@ static int feed_post_mortem() post_mortem.process.boot_gid = getegid(); getrlimit(RLIMIT_NOFILE, &post_mortem.process.limit_fd); -#if defined(RLIMIT_AS) - getrlimit(RLIMIT_AS, &post_mortem.process.limit_ram); -#elif defined(RLIMIT_DATA) getrlimit(RLIMIT_DATA, &post_mortem.process.limit_ram); -#endif if (strcmp(post_mortem.platform.utsname.sysname, "Linux") == 0) feed_post_mortem_linux(); @@ -2295,6 +2382,9 @@ static struct cli_kw_list cli_kws = {{ },{ {{ "debug", "dev", "sym", NULL }, "debug dev sym <addr> : resolve symbol address", debug_parse_cli_sym, NULL, NULL, NULL, ACCESS_EXPERT }, {{ "debug", "dev", "task", NULL }, "debug dev task <ptr> [wake|expire|kill] : show/wake/expire/kill task/tasklet", debug_parse_cli_task, NULL, NULL, NULL, ACCESS_EXPERT }, {{ "debug", "dev", "tkill", NULL }, "debug dev tkill [thr] [sig] : send signal to thread", debug_parse_cli_tkill, NULL, NULL, NULL, ACCESS_EXPERT }, +#if defined(DEBUG_DEV) + {{ "debug", "dev", "trace", NULL }, "debug dev trace [nbthr] : flood traces from that many threads", debug_parse_cli_trace, NULL, NULL, NULL, ACCESS_EXPERT }, +#endif {{ "debug", "dev", "warn", NULL }, "debug dev warn : call WARN_ON() and possibly crash", debug_parse_cli_warn, NULL, NULL, NULL, ACCESS_EXPERT }, {{ "debug", "dev", "write", NULL }, "debug dev write [size] : write that many bytes in return", debug_parse_cli_write, NULL, NULL, NULL, ACCESS_EXPERT }, |