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.
(cherry picked from commit 78a7cb648ca33823c06430cedc6859ea7e7cd5df)
[wt: backported to improve troubleshooting when the watchdog fires]
Signed-off-by: Willy Tarreau <w@1wt.eu>
diff --git a/src/debug.c b/src/debug.c
index 36cc9e7..79bea88 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -26,6 +26,7 @@
#include <proto/cli.h>
#include <proto/fd.h>
+#include <proto/hlua.h>
#include <proto/stream_interface.h>
#include <proto/task.h>
@@ -91,6 +92,7 @@
{
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");
@@ -117,6 +119,9 @@
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);
@@ -134,6 +139,30 @@
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