X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fscript%2Fcommon%2Fc_internal.cpp;h=df82dba146ec7ddcb5d0becc7446b743e8c71e17;hb=391eec9ee78fc9dfdc476ad2a8ed7755009e4a2f;hp=3d766a95557c52b347de62c26dd577941ed10e0f;hpb=813d819d153c78eb81893c208ba73c56237ea3d4;p=minetest.git diff --git a/src/script/common/c_internal.cpp b/src/script/common/c_internal.cpp index 3d766a955..df82dba14 100644 --- a/src/script/common/c_internal.cpp +++ b/src/script/common/c_internal.cpp @@ -18,15 +18,20 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "common/c_internal.h" +#include "util/numeric.h" #include "debug.h" #include "log.h" +#include "porting.h" #include "settings.h" +#include // std::find std::string script_get_backtrace(lua_State *L) { lua_rawgeti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_BACKTRACE); lua_call(L, 0, 1); - return luaL_checkstring(L, -1); + std::string result = luaL_checkstring(L, -1); + lua_pop(L, 1); + return result; } int script_exception_wrapper(lua_State *L, lua_CFunction f) @@ -44,7 +49,7 @@ int script_exception_wrapper(lua_State *L, lua_CFunction f) /* * Note that we can't get tracebacks for LUA_ERRMEM or LUA_ERRERR (without * hacking Lua internals). For LUA_ERRMEM, this is because memory errors will - * not execute the the error handler, and by the time lua_pcall returns the + * not execute the error handler, and by the time lua_pcall returns the * execution stack will have already been unwound. For LUA_ERRERR, there was * another error while trying to generate a backtrace from a LUA_ERRRUN. It is * presumed there is an error with the internal Lua state and thus not possible @@ -82,7 +87,7 @@ void script_error(lua_State *L, int pcall_result, const char *mod, const char *f err_descr = ""; char buf[256]; - snprintf(buf, sizeof(buf), "%s error from mod '%s' in callback %s(): ", + porting::mt_snprintf(buf, sizeof(buf), "%s error from mod '%s' in callback %s(): ", err_type, mod, fxn); std::string err_msg(buf); @@ -96,75 +101,68 @@ void script_error(lua_State *L, int pcall_result, const char *mod, const char *f throw LuaError(err_msg); } -// Push the list of callbacks (a lua table). -// Then push nargs arguments. -// Then call this function, which -// - runs the callbacks -// - replaces the table and arguments with the return value, -// computed depending on mode -void script_run_callbacks_f(lua_State *L, int nargs, - RunCallbacksMode mode, const char *fxn) +static void script_log_add_source(lua_State *L, std::string &message, int stack_depth) { - FATAL_ERROR_IF(lua_gettop(L) < nargs + 1, "Not enough arguments"); - - // Insert error handler - PUSH_ERROR_HANDLER(L); - int error_handler = lua_gettop(L) - nargs - 1; - lua_insert(L, error_handler); - - // Insert run_callbacks between error handler and table - lua_getglobal(L, "core"); - lua_getfield(L, -1, "run_callbacks"); - lua_remove(L, -2); - lua_insert(L, error_handler + 1); + lua_Debug ar; + + if (lua_getstack(L, stack_depth, &ar)) { + FATAL_ERROR_IF(!lua_getinfo(L, "Sl", &ar), "lua_getinfo() failed"); + message.append(" (at " + std::string(ar.short_src) + ":" + + std::to_string(ar.currentline) + ")"); + } else { + message.append(" (at ?:?)"); + } +} - // Insert mode after table - lua_pushnumber(L, (int) mode); - lua_insert(L, error_handler + 3); +bool script_log_unique(lua_State *L, std::string message, std::ostream &log_to, + int stack_depth) +{ + thread_local std::vector logged_messages; - // Stack now looks like this: - // ... ... + script_log_add_source(L, message, stack_depth); + u64 hash = murmur_hash_64_ua(message.data(), message.length(), 0xBADBABE); - int result = lua_pcall(L, nargs + 2, 1, error_handler); - if (result != 0) - script_error(L, result, NULL, fxn); + if (std::find(logged_messages.begin(), logged_messages.end(), hash) + == logged_messages.end()) { - lua_remove(L, error_handler); + logged_messages.emplace_back(hash); + log_to << message << std::endl; + return true; + } + return false; } -void log_deprecated(lua_State *L, const std::string &message) +DeprecatedHandlingMode get_deprecated_handling_mode() { - static bool configured = false; - static bool do_log = false; - static bool do_error = false; + static thread_local bool configured = false; + static thread_local DeprecatedHandlingMode ret = DeprecatedHandlingMode::Ignore; // Only read settings on first call if (!configured) { std::string value = g_settings->get("deprecated_lua_api_handling"); if (value == "log") { - do_log = true; + ret = DeprecatedHandlingMode::Log; } else if (value == "error") { - do_log = true; - do_error = true; + ret = DeprecatedHandlingMode::Error; } + configured = true; } - if (do_log) { - warningstream << message; - if (L) { // L can be NULL if we get called from scripting_game.cpp - lua_Debug ar; - FATAL_ERROR_IF(!lua_getstack(L, 2, &ar), "lua_getstack() failed"); - FATAL_ERROR_IF(!lua_getinfo(L, "Sl", &ar), "lua_getinfo() failed"); - warningstream << " (at " << ar.short_src << ":" << ar.currentline << ")"; - } - warningstream << std::endl; + return ret; +} - if (L) { - if (do_error) - script_error(L, LUA_ERRRUN, NULL, NULL); - else - infostream << script_get_backtrace(L) << std::endl; - } - } +void log_deprecated(lua_State *L, std::string message, int stack_depth) +{ + DeprecatedHandlingMode mode = get_deprecated_handling_mode(); + if (mode == DeprecatedHandlingMode::Ignore) + return; + + script_log_add_source(L, message, stack_depth); + warningstream << message << std::endl; + + if (mode == DeprecatedHandlingMode::Error) + script_error(L, LUA_ERRRUN, NULL, NULL); + else + infostream << script_get_backtrace(L) << std::endl; }