]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: lua: Increase debug information
authorThierry FOURNIER <thierry.fournier@ozon.io>
Thu, 7 Jun 2018 12:40:48 +0000 (14:40 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 8 Jun 2018 16:18:33 +0000 (18:18 +0200)
When an unrecoverable error raises, the user receive poor information
for the trouble shooting. For example:

   [ALERT] 157/143755 (21212) : Lua function 'hello-world': runtime error: memory allocation error: block too big.

Unfortunately, the memory allocation error can be throwed by many
function, and we have no informatio to reach the original cause.
This patch add the list of function called from the entry point to
the function in error, like this:

   [ALERT] 157/143755 (21212) : Lua function 'hello-world': runtime error: memory allocation error: block too big from [C] method 'req_get_headers', bug35.lua:2 global 'ee', bug35.lua:6 global 'ff', bug35.lua:10 C function line 9.

src/hlua.c

index 2f7fe99605a0027df83858075271076789d35fc6..716bd29cd4c3504b9396084a23f0e56d09dd55ca 100644 (file)
@@ -287,6 +287,63 @@ const char *hlua_get_top_error_string(lua_State *L)
        return lua_tostring(L, -1);
 }
 
+__LJMP static const char *hlua_traceback(lua_State *L)
+{
+       lua_Debug ar;
+       int level = 0;
+       struct chunk *msg = get_trash_chunk();
+       int filled = 0;
+
+       while (lua_getstack(L, level++, &ar)) {
+
+               /* Add separator */
+               if (filled)
+                       chunk_appendf(msg, ", ");
+               filled = 1;
+
+               /* Fill fields:
+                * 'S': fills in the fields source, short_src, linedefined, lastlinedefined, and what;
+                * 'l': fills in the field currentline;
+                * 'n': fills in the field name and namewhat;
+                * 't': fills in the field istailcall;
+                */
+               lua_getinfo(L, "Slnt", &ar);
+
+               /* Append code localisation */
+               if (ar.currentline > 0)
+                       chunk_appendf(msg, "%s:%d ", ar.short_src, ar.currentline);
+               else
+                       chunk_appendf(msg, "%s ", ar.short_src);
+
+               /*
+                * Get function name
+                *
+                * if namewhat is no empty, name is defined.
+                * what contains "Lua" for Lua function, "C" for C function,
+                * or "main" for main code.
+                */
+               if (*ar.namewhat != '\0' && ar.name != NULL)  /* is there a name from code? */
+                       chunk_appendf(msg, "%s '%s'", ar.namewhat, ar.name);  /* use it */
+
+               else if (*ar.what == 'm')  /* "main", the code is not executed in a function */
+                       chunk_appendf(msg, "main chunk");
+
+               else if (*ar.what != 'C')  /* for Lua functions, use <file:line> */
+                       chunk_appendf(msg, "C function line %d", ar.linedefined);
+
+               else  /* nothing left... */
+                       chunk_appendf(msg, "?");
+
+
+               /* Display tailed call */
+               if (ar.istailcall)
+                       chunk_appendf(msg, " ...");
+       }
+
+       return msg->str;
+}
+
+
 /* This function check the number of arguments available in the
  * stack. If the number of arguments available is not the same
  * then <nb> an error is throwed.
@@ -992,6 +1049,7 @@ static enum hlua_exec hlua_ctx_resume(struct hlua *lua, int yield_allowed)
 {
        int ret;
        const char *msg;
+       const char *trace;
 
        /* Initialise run time counter. */
        if (!HLUA_IS_RUNNING(lua))
@@ -1076,10 +1134,11 @@ resume_execution:
                msg = lua_tostring(lua->T, -1);
                lua_settop(lua->T, 0); /* Empty the stack. */
                lua_pop(lua->T, 1);
+               trace = hlua_traceback(lua->T);
                if (msg)
-                       lua_pushfstring(lua->T, "runtime error: %s", msg);
+                       lua_pushfstring(lua->T, "runtime error: %s from %s", msg, trace);
                else
-                       lua_pushfstring(lua->T, "unknown runtime error");
+                       lua_pushfstring(lua->T, "unknown runtime error from %s", trace);
                ret = HLUA_E_ERRMSG;
                break;