diff options
author | ShadowNinja <shadowninja@minetest.net> | 2013-12-18 16:35:55 -0500 |
---|---|---|
committer | ShadowNinja <shadowninja@minetest.net> | 2013-12-18 16:35:55 -0500 |
commit | 49cec3f78240ed6310a9b5dd05ce09a79ed5a12e (patch) | |
tree | 38e8199e49906357939e74b6ed0b00f6f54de976 /src/script | |
parent | 38d112033b3ba0ea0360fced334a279576aafc5d (diff) | |
download | minetest-49cec3f78240ed6310a9b5dd05ce09a79ed5a12e.tar.gz minetest-49cec3f78240ed6310a9b5dd05ce09a79ed5a12e.tar.bz2 minetest-49cec3f78240ed6310a9b5dd05ce09a79ed5a12e.zip |
Handle LuaErrors in Lua -> C++ calls on LuaJIT
Diffstat (limited to 'src/script')
-rw-r--r-- | src/script/common/c_content.cpp | 2 | ||||
-rw-r--r-- | src/script/common/c_internal.cpp | 12 | ||||
-rw-r--r-- | src/script/common/c_internal.h | 1 | ||||
-rw-r--r-- | src/script/common/c_types.cpp | 8 | ||||
-rw-r--r-- | src/script/common/c_types.h | 5 | ||||
-rw-r--r-- | src/script/cpp_api/s_base.cpp | 11 | ||||
-rw-r--r-- | src/script/cpp_api/s_inventory.cpp | 6 | ||||
-rw-r--r-- | src/script/cpp_api/s_nodemeta.cpp | 6 | ||||
-rw-r--r-- | src/script/cpp_api/s_server.cpp | 12 | ||||
-rw-r--r-- | src/script/lua_api/l_base.h | 2 | ||||
-rw-r--r-- | src/script/lua_api/l_craft.cpp | 28 | ||||
-rw-r--r-- | src/script/lua_api/l_item.cpp | 4 | ||||
-rw-r--r-- | src/script/lua_api/l_noise.cpp | 4 |
13 files changed, 64 insertions, 37 deletions
diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index d58479042..cf9f28d30 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -653,7 +653,7 @@ ItemStack read_item(lua_State* L, int index,Server* srv) } else { - throw LuaError(L, "Expecting itemstack, itemstring, table or nil"); + throw LuaError(NULL, "Expecting itemstack, itemstring, table or nil"); } } diff --git a/src/script/common/c_internal.cpp b/src/script/common/c_internal.cpp index 2866cfe86..90846676f 100644 --- a/src/script/common/c_internal.cpp +++ b/src/script/common/c_internal.cpp @@ -55,6 +55,18 @@ int script_error_handler(lua_State *L) { return 1; } +int script_exception_wrapper(lua_State *L, lua_CFunction f) +{ + try { + return f(L); // Call wrapped function and return result. + } catch (const char *s) { // Catch and convert exceptions. + lua_pushstring(L, s); + } catch (LuaError& e) { + lua_pushstring(L, e.what()); + } + return lua_error(L); // Rethrow as a Lua error. +} + void script_error(lua_State *L) { const char *s = lua_tostring(L, -1); diff --git a/src/script/common/c_internal.h b/src/script/common/c_internal.h index eb6aa06e8..f3ef18d70 100644 --- a/src/script/common/c_internal.h +++ b/src/script/common/c_internal.h @@ -66,6 +66,7 @@ enum RunCallbacksMode std::string script_get_backtrace(lua_State *L); int script_error_handler(lua_State *L); +int script_exception_wrapper(lua_State *L, lua_CFunction f); void script_error(lua_State *L); void script_run_callbacks(lua_State *L, int nargs, RunCallbacksMode mode); diff --git a/src/script/common/c_types.cpp b/src/script/common/c_types.cpp index a6faf9819..6ffad1cb1 100644 --- a/src/script/common/c_types.cpp +++ b/src/script/common/c_types.cpp @@ -23,10 +23,12 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common/c_internal.h" #include "itemdef.h" -LuaError::LuaError(lua_State *L, const std::string &s) +LuaError::LuaError(lua_State *L, const std::string &s) : + ServerError(s) { - m_s = "LuaError: " + s; - if (L) m_s += '\n' + script_get_backtrace(L); + if (L) { + m_s += '\n' + script_get_backtrace(L); + } } struct EnumString es_ItemType[] = diff --git a/src/script/common/c_types.h b/src/script/common/c_types.h index bc9f1cb96..709d4f34b 100644 --- a/src/script/common/c_types.h +++ b/src/script/common/c_types.h @@ -26,6 +26,8 @@ extern "C" { #include <iostream> +#include "exceptions.h" + struct EnumString { int num; @@ -50,7 +52,7 @@ public: } }; -class LuaError : public std::exception +class LuaError : public ServerError { public: LuaError(lua_State *L, const std::string &s); @@ -61,7 +63,6 @@ public: { return m_s.c_str(); } - std::string m_s; }; diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp index b957dc64f..898271743 100644 --- a/src/script/cpp_api/s_base.cpp +++ b/src/script/cpp_api/s_base.cpp @@ -29,6 +29,9 @@ with this program; if not, write to the Free Software Foundation, Inc., extern "C" { #include "lualib.h" +#if USE_LUAJIT + #include "luajit.h" +#endif } #include <stdio.h> @@ -73,6 +76,14 @@ ScriptApiBase::ScriptApiBase() lua_pushlightuserdata(m_luastack, this); lua_setfield(m_luastack, LUA_REGISTRYINDEX, "scriptapi"); + // If we are using LuaJIT add a C++ wrapper function to catch + // exceptions thrown in Lua -> C++ calls +#if USE_LUAJIT + lua_pushlightuserdata(m_luastack, (void*) script_exception_wrapper); + luaJIT_setmode(m_luastack, -1, LUAJIT_MODE_WRAPCFUNC | LUAJIT_MODE_ON); + lua_pop(m_luastack, 1); +#endif + m_server = 0; m_environment = 0; m_guiengine = 0; diff --git a/src/script/cpp_api/s_inventory.cpp b/src/script/cpp_api/s_inventory.cpp index 4ee6e4be0..8542f0292 100644 --- a/src/script/cpp_api/s_inventory.cpp +++ b/src/script/cpp_api/s_inventory.cpp @@ -54,7 +54,7 @@ int ScriptApiDetached::detached_inventory_AllowMove( if(lua_pcall(L, 7, 1, errorhandler)) scriptError(); if(!lua_isnumber(L, -1)) - throw LuaError(L, "allow_move should return a number"); + throw LuaError(NULL, "allow_move should return a number"); int ret = luaL_checkinteger(L, -1); lua_pop(L, 2); // Pop integer and error handler return ret; @@ -86,7 +86,7 @@ int ScriptApiDetached::detached_inventory_AllowPut( if(lua_pcall(L, 5, 1, errorhandler)) scriptError(); if(!lua_isnumber(L, -1)) - throw LuaError(L, "allow_put should return a number"); + throw LuaError(NULL, "allow_put should return a number"); int ret = luaL_checkinteger(L, -1); lua_pop(L, 2); // Pop integer and error handler return ret; @@ -118,7 +118,7 @@ int ScriptApiDetached::detached_inventory_AllowTake( if(lua_pcall(L, 5, 1, errorhandler)) scriptError(); if(!lua_isnumber(L, -1)) - throw LuaError(L, "allow_take should return a number"); + throw LuaError(NULL, "allow_take should return a number"); int ret = luaL_checkinteger(L, -1); lua_pop(L, 2); // Pop integer and error handler return ret; diff --git a/src/script/cpp_api/s_nodemeta.cpp b/src/script/cpp_api/s_nodemeta.cpp index 1f04383f1..d8fd4dcfe 100644 --- a/src/script/cpp_api/s_nodemeta.cpp +++ b/src/script/cpp_api/s_nodemeta.cpp @@ -61,7 +61,7 @@ int ScriptApiNodemeta::nodemeta_inventory_AllowMove(v3s16 p, scriptError(); lua_remove(L, errorhandler); // Remove error handler if(!lua_isnumber(L, -1)) - throw LuaError(L, "allow_metadata_inventory_move should return a number"); + throw LuaError(NULL, "allow_metadata_inventory_move should return a number"); int num = luaL_checkinteger(L, -1); lua_pop(L, 1); // Pop integer return num; @@ -99,7 +99,7 @@ int ScriptApiNodemeta::nodemeta_inventory_AllowPut(v3s16 p, scriptError(); lua_remove(L, errorhandler); // Remove error handler if(!lua_isnumber(L, -1)) - throw LuaError(L, "allow_metadata_inventory_put should return a number"); + throw LuaError(NULL, "allow_metadata_inventory_put should return a number"); int num = luaL_checkinteger(L, -1); lua_pop(L, 1); // Pop integer return num; @@ -137,7 +137,7 @@ int ScriptApiNodemeta::nodemeta_inventory_AllowTake(v3s16 p, scriptError(); lua_remove(L, errorhandler); // Remove error handler if(!lua_isnumber(L, -1)) - throw LuaError(L, "allow_metadata_inventory_take should return a number"); + throw LuaError(NULL, "allow_metadata_inventory_take should return a number"); int num = luaL_checkinteger(L, -1); lua_pop(L, 1); // Pop integer return num; diff --git a/src/script/cpp_api/s_server.cpp b/src/script/cpp_api/s_server.cpp index 4baf90636..98320b578 100644 --- a/src/script/cpp_api/s_server.cpp +++ b/src/script/cpp_api/s_server.cpp @@ -33,7 +33,7 @@ bool ScriptApiServer::getAuth(const std::string &playername, getAuthHandler(); lua_getfield(L, -1, "get_auth"); if(lua_type(L, -1) != LUA_TFUNCTION) - throw LuaError(L, "Authentication handler missing get_auth"); + throw LuaError(NULL, "Authentication handler missing get_auth"); lua_pushstring(L, playername.c_str()); if(lua_pcall(L, 1, 1, errorhandler)) scriptError(); @@ -48,13 +48,13 @@ bool ScriptApiServer::getAuth(const std::string &playername, std::string password; bool found = getstringfield(L, -1, "password", password); if(!found) - throw LuaError(L, "Authentication handler didn't return password"); + throw LuaError(NULL, "Authentication handler didn't return password"); if(dst_password) *dst_password = password; lua_getfield(L, -1, "privileges"); if(!lua_istable(L, -1)) - throw LuaError(L, "Authentication handler didn't return privilege table"); + throw LuaError(NULL, "Authentication handler didn't return privilege table"); if(dst_privs) readPrivileges(-1, *dst_privs); lua_pop(L, 1); @@ -74,7 +74,7 @@ void ScriptApiServer::getAuthHandler() } lua_remove(L, -2); // Remove minetest if(lua_type(L, -1) != LUA_TTABLE) - throw LuaError(L, "Authentication handler table not valid"); + throw LuaError(NULL, "Authentication handler table not valid"); } void ScriptApiServer::readPrivileges(int index, std::set<std::string> &result) @@ -108,7 +108,7 @@ void ScriptApiServer::createAuth(const std::string &playername, lua_getfield(L, -1, "create_auth"); lua_remove(L, -2); // Remove auth handler if(lua_type(L, -1) != LUA_TFUNCTION) - throw LuaError(L, "Authentication handler missing create_auth"); + throw LuaError(NULL, "Authentication handler missing create_auth"); lua_pushstring(L, playername.c_str()); lua_pushstring(L, password.c_str()); if(lua_pcall(L, 2, 0, errorhandler)) @@ -128,7 +128,7 @@ bool ScriptApiServer::setPassword(const std::string &playername, lua_getfield(L, -1, "set_password"); lua_remove(L, -2); // Remove auth handler if(lua_type(L, -1) != LUA_TFUNCTION) - throw LuaError(L, "Authentication handler missing set_password"); + throw LuaError(NULL, "Authentication handler missing set_password"); lua_pushstring(L, playername.c_str()); lua_pushstring(L, password.c_str()); if(lua_pcall(L, 2, 1, errorhandler)) diff --git a/src/script/lua_api/l_base.h b/src/script/lua_api/l_base.h index 808043bd4..694ce5a1e 100644 --- a/src/script/lua_api/l_base.h +++ b/src/script/lua_api/l_base.h @@ -48,7 +48,7 @@ protected: ScriptApiBase *scriptIface = getScriptApiBase(L); T *scriptIfaceDowncast = dynamic_cast<T*>(scriptIface); if (!scriptIfaceDowncast) { - throw LuaError(L, "Requested unavailable ScriptApi - core engine bug!"); + throw LuaError(NULL, "Requested unavailable ScriptApi - core engine bug!"); } return scriptIfaceDowncast; } diff --git a/src/script/lua_api/l_craft.cpp b/src/script/lua_api/l_craft.cpp index 035abb78d..ef13aa82c 100644 --- a/src/script/lua_api/l_craft.cpp +++ b/src/script/lua_api/l_craft.cpp @@ -150,16 +150,16 @@ int ModApiCraft::l_register_craft(lua_State *L) if(type == "shaped"){ std::string output = getstringfield_default(L, table, "output", ""); if(output == "") - throw LuaError(L, "Crafting definition is missing an output"); + throw LuaError(NULL, "Crafting definition is missing an output"); int width = 0; std::vector<std::string> recipe; lua_getfield(L, table, "recipe"); if(lua_isnil(L, -1)) - throw LuaError(L, "Crafting definition is missing a recipe" + throw LuaError(NULL, "Crafting definition is missing a recipe" " (output=\"" + output + "\")"); if(!readCraftRecipeShaped(L, -1, width, recipe)) - throw LuaError(L, "Invalid crafting recipe" + throw LuaError(NULL, "Invalid crafting recipe" " (output=\"" + output + "\")"); CraftReplacements replacements; @@ -167,7 +167,7 @@ int ModApiCraft::l_register_craft(lua_State *L) if(!lua_isnil(L, -1)) { if(!readCraftReplacements(L, -1, replacements)) - throw LuaError(L, "Invalid replacements" + throw LuaError(NULL, "Invalid replacements" " (output=\"" + output + "\")"); } @@ -181,17 +181,17 @@ int ModApiCraft::l_register_craft(lua_State *L) else if(type == "shapeless"){ std::string output = getstringfield_default(L, table, "output", ""); if(output == "") - throw LuaError(L, "Crafting definition (shapeless)" + throw LuaError(NULL, "Crafting definition (shapeless)" " is missing an output"); std::vector<std::string> recipe; lua_getfield(L, table, "recipe"); if(lua_isnil(L, -1)) - throw LuaError(L, "Crafting definition (shapeless)" + throw LuaError(NULL, "Crafting definition (shapeless)" " is missing a recipe" " (output=\"" + output + "\")"); if(!readCraftRecipeShapeless(L, -1, recipe)) - throw LuaError(L, "Invalid crafting recipe" + throw LuaError(NULL, "Invalid crafting recipe" " (output=\"" + output + "\")"); CraftReplacements replacements; @@ -199,7 +199,7 @@ int ModApiCraft::l_register_craft(lua_State *L) if(!lua_isnil(L, -1)) { if(!readCraftReplacements(L, -1, replacements)) - throw LuaError(L, "Invalid replacements" + throw LuaError(NULL, "Invalid replacements" " (output=\"" + output + "\")"); } @@ -224,12 +224,12 @@ int ModApiCraft::l_register_craft(lua_State *L) else if(type == "cooking"){ std::string output = getstringfield_default(L, table, "output", ""); if(output == "") - throw LuaError(L, "Crafting definition (cooking)" + throw LuaError(NULL, "Crafting definition (cooking)" " is missing an output"); std::string recipe = getstringfield_default(L, table, "recipe", ""); if(recipe == "") - throw LuaError(L, "Crafting definition (cooking)" + throw LuaError(NULL, "Crafting definition (cooking)" " is missing a recipe" " (output=\"" + output + "\")"); @@ -240,7 +240,7 @@ int ModApiCraft::l_register_craft(lua_State *L) if(!lua_isnil(L, -1)) { if(!readCraftReplacements(L, -1, replacements)) - throw LuaError(L, "Invalid replacements" + throw LuaError(NULL, "Invalid replacements" " (cooking output=\"" + output + "\")"); } @@ -254,7 +254,7 @@ int ModApiCraft::l_register_craft(lua_State *L) else if(type == "fuel"){ std::string recipe = getstringfield_default(L, table, "recipe", ""); if(recipe == "") - throw LuaError(L, "Crafting definition (fuel)" + throw LuaError(NULL, "Crafting definition (fuel)" " is missing a recipe"); float burntime = getfloatfield_default(L, table, "burntime", 1.0); @@ -264,7 +264,7 @@ int ModApiCraft::l_register_craft(lua_State *L) if(!lua_isnil(L, -1)) { if(!readCraftReplacements(L, -1, replacements)) - throw LuaError(L, "Invalid replacements" + throw LuaError(NULL, "Invalid replacements" " (fuel recipe=\"" + recipe + "\")"); } @@ -274,7 +274,7 @@ int ModApiCraft::l_register_craft(lua_State *L) } else { - throw LuaError(L, "Unknown crafting definition type: \"" + type + "\""); + throw LuaError(NULL, "Unknown crafting definition type: \"" + type + "\""); } lua_pop(L, 1); diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp index 512cd7398..4b5c89792 100644 --- a/src/script/lua_api/l_item.cpp +++ b/src/script/lua_api/l_item.cpp @@ -470,7 +470,7 @@ int ModApiItemMod::l_register_item_raw(lua_State *L) name = lua_tostring(L, -1); verbosestream<<"register_item_raw: "<<name<<std::endl; } else { - throw LuaError(L, "register_item_raw: name is not defined or not a string"); + throw LuaError(NULL, "register_item_raw: name is not defined or not a string"); } // Check if on_use is defined @@ -500,7 +500,7 @@ int ModApiItemMod::l_register_item_raw(lua_State *L) content_t id = ndef->set(f.name, f); if(id > MAX_REGISTERED_CONTENT){ - throw LuaError(L, "Number of registerable nodes (" + throw LuaError(NULL, "Number of registerable nodes (" + itos(MAX_REGISTERED_CONTENT+1) + ") exceeded (" + name + ")"); } diff --git a/src/script/lua_api/l_noise.cpp b/src/script/lua_api/l_noise.cpp index 4b0c7932d..4ca9992af 100644 --- a/src/script/lua_api/l_noise.cpp +++ b/src/script/lua_api/l_noise.cpp @@ -330,10 +330,10 @@ int LuaPseudoRandom::l_next(lua_State *L) max = luaL_checkinteger(L, 3); if(max < min){ errorstream<<"PseudoRandom.next(): max="<<max<<" min="<<min<<std::endl; - throw LuaError(L, "PseudoRandom.next(): max < min"); + throw LuaError(NULL, "PseudoRandom.next(): max < min"); } if(max - min != 32767 && max - min > 32767/5) - throw LuaError(L, "PseudoRandom.next() max-min is not 32767" + throw LuaError(NULL, "PseudoRandom.next() max-min is not 32767" " and is > 32768/5. This is disallowed due to" " the bad random distribution the" " implementation would otherwise make."); |