]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
DEBUG: lua: precisely identify if stream is stuck inside lua or not
authorAurelien DARRAGON <adarragon@haproxy.com>
Mon, 11 Mar 2024 23:22:44 +0000 (00:22 +0100)
committerAurelien DARRAGON <adarragon@haproxy.com>
Wed, 13 Mar 2024 08:24:46 +0000 (09:24 +0100)
When ha_panic() is called by the watchdog, we try to guess from
ha_task_dump() and ha_thread_dump_one() if the thread was stuck while
executing lua from the stream context. However we consider this is the
case by simply checking if the stream hlua context was set, but this is
not very precise because if the hlua context is set, then it simply means
that at least one lua instruction was executed at the stream level, not
that the stuck was currently executing lua when the panic occured.

This is especially true with filters, one could simply register a lua
filter that does nothing but this will still end up initializing the
stream hlua context for each stream. If the thread end up being stuck
during the stream handling, then debug dumping functions will report
that the stream was stuck while handling lua, which is not necessarilly
true, and could in fact confuse us even more.

So here we take another approach, we add the BUSY flag to hlua context:
this flag is set by hlua_ctx_resume() around lua_resume() call, this way
we can precisely tell if the thread was handling lua when it was
interrupted, and we rely on this flag in debug functions to check if the
thread was effectively stuck inside lua or not while processing the stream

No backport needed unless a commit depends on it.

include/haproxy/hlua-t.h
include/haproxy/hlua.h
src/debug.c
src/hlua.c

index 2672ffdcf4f5aa32843e68ccadbd6e4613fe62fd..af54d86943e6ff48329005b4969bf919b2c60f34 100644 (file)
@@ -67,6 +67,7 @@ struct stream;
 #define HLUA_WAKEREQWR 0x00000008
 #define HLUA_EXIT      0x00000010
 #define HLUA_NOYIELD   0x00000020
+#define HLUA_BUSY      0x00000040
 
 #define HLUA_F_AS_STRING    0x01
 #define HLUA_F_MAY_USE_HTTP 0x02
index 3c67ccea8442c4c2b75f7fd83e648db9c8e80f71..18fad9ff2c030a3776a0f3bd59df0329934277fe 100644 (file)
@@ -30,6 +30,9 @@
 #define HLUA_SET_RUN(__hlua)         do {(__hlua)->flags |= HLUA_RUN;} while(0)
 #define HLUA_CLR_RUN(__hlua)         do {(__hlua)->flags &= ~HLUA_RUN;} while(0)
 #define HLUA_IS_RUNNING(__hlua)      ((__hlua)->flags & HLUA_RUN)
+#define HLUA_SET_BUSY(__hlua)        do {(__hlua)->flags |= HLUA_BUSY;} while(0)
+#define HLUA_CLR_BUSY(__hlua)        do {(__hlua)->flags &= ~HLUA_BUSY;} while(0)
+#define HLUA_IS_BUSY(__hlua)         ((__hlua)->flags & HLUA_BUSY)
 #define HLUA_SET_CTRLYIELD(__hlua)   do {(__hlua)->flags |= HLUA_CTRLYIELD;} while(0)
 #define HLUA_CLR_CTRLYIELD(__hlua)   do {(__hlua)->flags &= ~HLUA_CTRLYIELD;} while(0)
 #define HLUA_IS_CTRLYIELDING(__hlua) ((__hlua)->flags & HLUA_CTRLYIELD)
index d1526e1d44dc17df6c324b3a926cba9de9e4085f..ff548037373a82aa2cfdaf01ea814f6b85707004 100644 (file)
@@ -302,7 +302,7 @@ void ha_thread_dump_one(int thr, int from_signal)
                        const struct stream *s = (const struct stream *)th_ctx->current->context;
                        struct hlua *hlua = s ? s->hlua : NULL;
 
-                       if (hlua && hlua->T) {
+                       if (hlua && HLUA_IS_BUSY(hlua)) {
                                mark_tainted(TAINTED_LUA_STUCK);
                                if (hlua->state_id == 0)
                                        mark_tainted(TAINTED_LUA_STUCK_SHARED);
@@ -417,7 +417,8 @@ void ha_task_dump(struct buffer *buf, const struct task *task, const char *pfx)
 
 #ifdef USE_LUA
        hlua = NULL;
-       if (s && (hlua = s->hlua)) {
+       if (s && s->hlua && HLUA_IS_BUSY(s->hlua)) {
+               hlua = s->hlua;
                chunk_appendf(buf, "%sCurrent executing Lua from a stream analyser -- ", pfx);
        }
        else if (task->process == hlua_process_task && (hlua = task->context)) {
index 7f1dfed6da47e31b97e46394a8e73b5085f0ab14..e0a5bfdff92cccd8cdfdad96e2eb8af9f1aa35b3 100644 (file)
@@ -1803,6 +1803,8 @@ resume_execution:
        /* start the timer as we're about to start lua processing */
        hlua_timer_start(&lua->timer);
 
+       HLUA_SET_BUSY(lua);
+
        /* Call the function. */
 #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 504
        ret = lua_resume(lua->T, hlua_states[lua->state_id], lua->nargs, &nres);
@@ -1810,6 +1812,8 @@ resume_execution:
        ret = lua_resume(lua->T, hlua_states[lua->state_id], lua->nargs);
 #endif
 
+       HLUA_CLR_BUSY(lua);
+
        /* out of lua processing, stop the timer */
        hlua_timer_stop(&lua->timer);