]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
Print stack trace on lua errors.
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 14 Sep 2015 20:37:34 +0000 (21:37 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 14 Sep 2015 20:37:34 +0000 (21:37 +0100)
src/lua/lua_common.c
src/lua/lua_common.h
src/lua/lua_config.c

index 2c8403e96bdd625c6ae48bd88b9a22662805932e..3841ffe14362040762751f2e6399712ec0cf7695 100644 (file)
@@ -291,6 +291,8 @@ rspamd_init_lua_filters (struct rspamd_config *cfg)
        GList *cur;
        struct script_module *module;
        lua_State *L = cfg->lua_state;
+       GString *tb;
+       gint err_idx;
 
        rspamd_lua_set_path (L, cfg);
        cur = g_list_first (cfg->script_modules);
@@ -303,10 +305,17 @@ rspamd_init_lua_filters (struct rspamd_config *cfg)
                                continue;
                        }
 
+                       tb = g_string_new ("");
+                       lua_pushlightuserdata (L, tb);
+                       lua_pushcclosure (L, &rspamd_lua_traceback, 1);
+                       err_idx = lua_gettop (L);
+
                        if (luaL_loadfile (L, module->path) != 0) {
-                               msg_info_config ("load of %s failed: %s", module->path,
+                               msg_err_config ("load of %s failed: %s", module->path,
                                        lua_tostring (L, -1));
                                cur = g_list_next (cur);
+                               g_string_free (tb, TRUE);
+                               lua_pop (L, 1); /* Error function */
                                continue;
                        }
 
@@ -316,21 +325,18 @@ rspamd_init_lua_filters (struct rspamd_config *cfg)
                        *pcfg = cfg;
                        lua_setglobal (L, "rspamd_config");
 
-                       /* do the call (0 arguments, N result) */
-                       if (lua_pcall (L, 0, LUA_MULTRET, 0) != 0) {
-                               msg_info_config ("init of %s failed: %s", module->path,
-                                       lua_tostring (L, -1));
+                       if (lua_pcall (L, 0, 0, err_idx) != 0) {
+                               msg_err_config ("init of %s failed: %v",
+                                               module->path,
+                                               tb);
                                cur = g_list_next (cur);
+                               g_string_free (tb, TRUE);
+                               lua_pop (L, 1);
                                continue;
                        }
-                       if (lua_gettop (L) != 0) {
-                               if (lua_tonumber (L, -1) == -1) {
-                                       msg_info_config (
-                                               "%s returned -1 that indicates configuration error",
-                                               module->path);
-                               }
-                               lua_pop (L, lua_gettop (L));
-                       }
+
+                       g_string_free (tb, TRUE);
+                       lua_pop (L, 1); /* Error function */
                }
                cur = g_list_next (cur);
        }
@@ -806,3 +812,23 @@ rspamd_lua_parse_table_arguments (lua_State *L, gint pos,
 
        return TRUE;
 }
+
+gint
+rspamd_lua_traceback (lua_State *L)
+{
+       lua_Debug d;
+       GString *tb = lua_touserdata (L, lua_upvalueindex(1));
+       const gchar *msg = lua_tostring (L, 1);
+       gint i = 1;
+
+       g_string_append_printf (tb, "%s; trace:", msg);
+
+       while (lua_getstack (L, i++, &d)) {
+               lua_getinfo (L, "nSl", &d);
+               g_string_append_printf (tb, " [%d]:{%s:%d - %s [%s]};",
+                               i - 1, d.short_src, d.currentline,
+                               (d.name ? d.name : "<unknown>"), d.what);
+       }
+
+       return 0;
+}
index 5321d0409141a58a2ce0490a043908f000d11213..b2b2750b585d1e0e0cb859c9fa2d6cc500cb3332 100644 (file)
@@ -281,5 +281,6 @@ gboolean rspamd_lua_parse_table_arguments (lua_State *L, gint pos,
                GError **err, const gchar *extraction_pattern, ...);
 
 
+gint rspamd_lua_traceback (lua_State *L);
 #endif /* WITH_LUA */
 #endif /* RSPAMD_LUA_H */
index 43a6fb1357cf89d61009c104ed6a51ddb2607af4..5f42a528c2ae1a76cf2df51860aa7fef3234b732 100644 (file)
@@ -872,56 +872,72 @@ lua_metric_symbol_callback (struct rspamd_task *task, gpointer ud)
 {
        struct lua_callback_data *cd = ud;
        struct rspamd_task **ptask;
-       gint level = lua_gettop (cd->L), nresults;
+       gint level = lua_gettop (cd->L), nresults, err_idx;
+       lua_State *L = cd->L;
+       GString *tb;
+
+       tb = g_string_new ("");
+       lua_pushlightuserdata (L, tb);
+       lua_pushcclosure (L, &rspamd_lua_traceback, 1);
+       err_idx = lua_gettop (L);
+
+       level ++;
 
        if (cd->cb_is_ref) {
-               lua_rawgeti (cd->L, LUA_REGISTRYINDEX, cd->callback.ref);
+               lua_rawgeti (L, LUA_REGISTRYINDEX, cd->callback.ref);
        }
        else {
-               lua_getglobal (cd->L, cd->callback.name);
+               lua_getglobal (L, cd->callback.name);
        }
-       ptask = lua_newuserdata (cd->L, sizeof (struct rspamd_task *));
-       rspamd_lua_setclass (cd->L, "rspamd{task}", -1);
+
+       ptask = lua_newuserdata (L, sizeof (struct rspamd_task *));
+       rspamd_lua_setclass (L, "rspamd{task}", -1);
        *ptask = task;
 
-       if (lua_pcall (cd->L, 1, LUA_MULTRET, 0) != 0) {
-               msg_info_task ("call to (%s)%s failed: %s", cd->symbol,
-                       cd->cb_is_ref ? "local function" : cd->callback.name,
-                       lua_tostring (cd->L, -1));
-       }
+       if (lua_pcall (L, 1, LUA_MULTRET, err_idx) != 0) {
 
-       nresults = lua_gettop (cd->L) - level;
-       if (nresults >= 1) {
-               /* Function returned boolean, so maybe we need to insert result? */
-               gboolean res;
-               GList *opts = NULL;
-               gint i;
-               gdouble flag = 1.0;
-
-               if (lua_type (cd->L, level + 1) == LUA_TBOOLEAN) {
-                       res = lua_toboolean (cd->L, level + 1);
-                       if (res) {
-                               gint first_opt = 2;
-
-                               if (lua_type (cd->L, level + 2) == LUA_TNUMBER) {
-                                       flag = lua_tonumber (cd->L, level + 2);
-                                       /* Shift opt index */
-                                       first_opt = 3;
-                               }
+               msg_err_task ("call to (%s)%s failed: %v", cd->symbol,
+                       cd->cb_is_ref ? "local function" : cd->callback.name, tb);
+       }
+       else {
+               nresults = lua_gettop (L) - level;
+
+               if (nresults >= 1) {
+                       /* Function returned boolean, so maybe we need to insert result? */
+                       gboolean res;
+                       GList *opts = NULL;
+                       gint i;
+                       gdouble flag = 1.0;
+
+                       if (lua_type (cd->L, level + 1) == LUA_TBOOLEAN) {
+                               res = lua_toboolean (L, level + 1);
+                               if (res) {
+                                       gint first_opt = 2;
+
+                                       if (lua_type (L, level + 2) == LUA_TNUMBER) {
+                                               flag = lua_tonumber (L, level + 2);
+                                               /* Shift opt index */
+                                               first_opt = 3;
+                                       }
 
-                               for (i = lua_gettop (cd->L); i >= level + first_opt; i --) {
-                                       if (lua_type (cd->L, i) == LUA_TSTRING) {
-                                               const char *opt = lua_tostring (cd->L, i);
+                                       for (i = lua_gettop (L); i >= level + first_opt; i--) {
+                                               if (lua_type (L, i) == LUA_TSTRING) {
+                                                       const char *opt = lua_tostring (L, i);
 
-                                               opts = g_list_prepend (opts,
-                                                       rspamd_mempool_strdup (task->task_pool, opt));
+                                                       opts = g_list_prepend (opts,
+                                                                       rspamd_mempool_strdup (task->task_pool,
+                                                                                       opt));
+                                               }
                                        }
+                                       rspamd_task_insert_result (task, cd->symbol, flag, opts);
                                }
-                               rspamd_task_insert_result (task, cd->symbol, flag, opts);
                        }
+                       lua_pop (L, nresults);
                }
-               lua_pop (cd->L, nresults);
        }
+
+       g_string_free (tb, TRUE);
+       lua_pop (L, 1); /* Error function */
 }
 
 static gint