From: Willy Tarreau Date: Wed, 21 Aug 2019 12:16:02 +0000 (+0200) Subject: MEDIUM: debug: make the thread dump code show Lua backtraces X-Git-Tag: v2.1-dev2~201 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=78a7cb648ca33823c06430cedc6859ea7e7cd5df;p=thirdparty%2Fhaproxy.git MEDIUM: debug: make the thread dump code show Lua backtraces When we dump a thread's state (show thread, panic) we don't know if anything is happening in Lua, which can be problematic especially when calling external functions. With this patch, the thread dump code can now detect if we're running in a global Lua task (hlua_process_task), or in a TCP or HTTP Lua service (task_run_applet and applet.fct == hlua_applet_tcp_fct or http_applet_http_fct), or a fetch/converter from an analyser (s->hlua != NULL). In such situations, it's able to append a formatted Lua backtrace of the Lua execution path with function names, file names and line numbers. Note that a shorter alternative could be to call "luaL_where(hlua->T,0)" which only prints the current location, but it's not necessarily sufficient for complex code. --- diff --git a/src/debug.c b/src/debug.c index 3ea5ae4024..409bd2cbd4 100644 --- a/src/debug.c +++ b/src/debug.c @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -90,6 +91,7 @@ void ha_task_dump(struct buffer *buf, const struct task *task, const char *pfx) { const struct stream *s = NULL; const struct appctx __maybe_unused *appctx = NULL; + struct hlua __maybe_unused *hlua = NULL; if (!task) { chunk_appendf(buf, "0\n"); @@ -116,6 +118,9 @@ void ha_task_dump(struct buffer *buf, const struct task *task, const char *pfx) task->process == process_stream ? "process_stream" : task->process == task_run_applet ? "task_run_applet" : task->process == si_cs_io_cb ? "si_cs_io_cb" : +#ifdef USE_LUA + task->process == hlua_process_task ? "hlua_process_task" : +#endif "?", task->context); @@ -133,6 +138,30 @@ void ha_task_dump(struct buffer *buf, const struct task *task, const char *pfx) if (s) stream_dump(buf, s, pfx, '\n'); + +#ifdef USE_LUA + hlua = NULL; + if (s && (hlua = s->hlua)) { + chunk_appendf(buf, "%sCurrent executing Lua from a stream analyser -- ", pfx); + } + else if (task->process == hlua_process_task && (hlua = task->context)) { + chunk_appendf(buf, "%sCurrent executing a Lua task -- ", pfx); + } + else if (task->process == task_run_applet && (appctx = task->context) && + (appctx->applet->fct == hlua_applet_tcp_fct && (hlua = appctx->ctx.hlua_apptcp.hlua))) { + chunk_appendf(buf, "%sCurrent executing a Lua TCP service -- ", pfx); + } + else if (task->process == task_run_applet && (appctx = task->context) && + (appctx->applet->fct == hlua_applet_http_fct && (hlua = appctx->ctx.hlua_apphttp.hlua))) { + chunk_appendf(buf, "%sCurrent executing a Lua HTTP service -- ", pfx); + } + + if (hlua) { + luaL_traceback(hlua->T, hlua->T, NULL, 0); + if (!append_prefixed_str(buf, lua_tostring(hlua->T, -1), pfx, '\n', 1)) + b_putchr(buf, '\n'); + } +#endif } /* This function dumps all profiling settings. It returns 0 if the output