From 49cec3f78240ed6310a9b5dd05ce09a79ed5a12e Mon Sep 17 00:00:00 2001 From: ShadowNinja Date: Wed, 18 Dec 2013 16:35:55 -0500 Subject: [PATCH] Handle LuaErrors in Lua -> C++ calls on LuaJIT --- src/cmake_config.h.in | 1 + src/config.h | 3 + src/exceptions.h | 115 ++++++++++------------------- src/game.cpp | 10 +-- src/script/common/c_content.cpp | 2 +- src/script/common/c_internal.cpp | 12 +++ src/script/common/c_internal.h | 1 + src/script/common/c_types.cpp | 8 +- src/script/common/c_types.h | 5 +- src/script/cpp_api/s_base.cpp | 11 +++ src/script/cpp_api/s_inventory.cpp | 6 +- src/script/cpp_api/s_nodemeta.cpp | 6 +- src/script/cpp_api/s_server.cpp | 12 +-- src/script/lua_api/l_base.h | 2 +- src/script/lua_api/l_craft.cpp | 28 +++---- src/script/lua_api/l_item.cpp | 4 +- src/script/lua_api/l_noise.cpp | 4 +- src/server.h | 17 ----- 18 files changed, 113 insertions(+), 134 deletions(-) diff --git a/src/cmake_config.h.in b/src/cmake_config.h.in index 7cc2fb99e..75e448f79 100644 --- a/src/cmake_config.h.in +++ b/src/cmake_config.h.in @@ -12,6 +12,7 @@ #define CMAKE_USE_FREETYPE @USE_FREETYPE@ #define CMAKE_STATIC_SHAREDIR "@SHAREDIR@" #define CMAKE_USE_LEVELDB @USE_LEVELDB@ +#define CMAKE_USE_LUAJIT @USE_LUAJIT@ #ifdef NDEBUG #define CMAKE_BUILD_TYPE "Release" diff --git a/src/config.h b/src/config.h index 652c9008a..1c0aac4f2 100644 --- a/src/config.h +++ b/src/config.h @@ -14,6 +14,7 @@ #define USE_FREETYPE 0 #define STATIC_SHAREDIR "" #define USE_LEVELDB 0 +#define USE_LUAJIT 0 #ifdef USE_CMAKE_CONFIG_H #include "cmake_config.h" @@ -33,6 +34,8 @@ #define STATIC_SHAREDIR CMAKE_STATIC_SHAREDIR #undef USE_LEVELDB #define USE_LEVELDB CMAKE_USE_LEVELDB + #undef USE_LUAJIT + #define USE_LUAJIT CMAKE_USE_LUAJIT #endif #endif diff --git a/src/exceptions.h b/src/exceptions.h index 085b42417..6fb97f3ed 100644 --- a/src/exceptions.h +++ b/src/exceptions.h @@ -21,132 +21,99 @@ with this program; if not, write to the Free Software Foundation, Inc., #define EXCEPTIONS_HEADER #include +#include + class BaseException : public std::exception { public: - BaseException(const char *s) + BaseException(const std::string s) throw() { m_s = s; } + ~BaseException() throw() {} virtual const char * what() const throw() { - return m_s; + return m_s.c_str(); } - const char *m_s; +protected: + std::string m_s; }; -class AsyncQueuedException : public BaseException -{ +class AsyncQueuedException : public BaseException { public: - AsyncQueuedException(const char *s): - BaseException(s) - {} + AsyncQueuedException(std::string s): BaseException(s) {} }; -class NotImplementedException : public BaseException -{ +class NotImplementedException : public BaseException { public: - NotImplementedException(const char *s): - BaseException(s) - {} + NotImplementedException(std::string s): BaseException(s) {} }; -class AlreadyExistsException : public BaseException -{ +class AlreadyExistsException : public BaseException { public: - AlreadyExistsException(const char *s): - BaseException(s) - {} + AlreadyExistsException(std::string s): BaseException(s) {} }; -class VersionMismatchException : public BaseException -{ +class VersionMismatchException : public BaseException { public: - VersionMismatchException(const char *s): - BaseException(s) - {} + VersionMismatchException(std::string s): BaseException(s) {} }; -class FileNotGoodException : public BaseException -{ +class FileNotGoodException : public BaseException { public: - FileNotGoodException(const char *s): - BaseException(s) - {} + FileNotGoodException(std::string s): BaseException(s) {} }; -class SerializationError : public BaseException -{ +class SerializationError : public BaseException { public: - SerializationError(const char *s): - BaseException(s) - {} + SerializationError(std::string s): BaseException(s) {} }; -class LoadError : public BaseException -{ +class LoadError : public BaseException { public: - LoadError(const char *s): - BaseException(s) - {} + LoadError(std::string s): BaseException(s) {} }; -class ContainerFullException : public BaseException -{ +class ContainerFullException : public BaseException { public: - ContainerFullException(const char *s): - BaseException(s) - {} + ContainerFullException(std::string s): BaseException(s) {} }; -class SettingNotFoundException : public BaseException -{ +class SettingNotFoundException : public BaseException { public: - SettingNotFoundException(const char *s): - BaseException(s) - {} + SettingNotFoundException(std::string s): BaseException(s) {} }; -class InvalidFilenameException : public BaseException -{ +class InvalidFilenameException : public BaseException { public: - InvalidFilenameException(const char *s): - BaseException(s) - {} + InvalidFilenameException(std::string s): BaseException(s) {} }; -class ProcessingLimitException : public BaseException -{ +class ProcessingLimitException : public BaseException { public: - ProcessingLimitException(const char *s): - BaseException(s) - {} + ProcessingLimitException(std::string s): BaseException(s) {} }; -class CommandLineError : public BaseException -{ +class CommandLineError : public BaseException { public: - CommandLineError(const char *s): - BaseException(s) - {} + CommandLineError(std::string s): BaseException(s) {} }; -class ItemNotFoundException : public BaseException -{ +class ItemNotFoundException : public BaseException { public: - ItemNotFoundException(const char *s): - BaseException(s) - {} + ItemNotFoundException(std::string s): BaseException(s) {} +}; + +class ServerError : public BaseException { +public: + ServerError(std::string s): BaseException(s) {} }; // Only used on Windows (SEH) -class FatalSystemException : public BaseException -{ +class FatalSystemException : public BaseException { public: - FatalSystemException(const char *s): - BaseException(s) - {} + FatalSystemException(std::string s): BaseException(s) {} }; /* @@ -159,7 +126,7 @@ public: InvalidPositionException(): BaseException("Somebody tried to get/set something in a nonexistent position.") {} - InvalidPositionException(const char *s): + InvalidPositionException(std::string s): BaseException(s) {} }; diff --git a/src/game.cpp b/src/game.cpp index cc5d3d81d..6f48870ad 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -3438,14 +3438,12 @@ void the_game( L" running a different version of Minetest."; errorstream< +#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 @@ -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 &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(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 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 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: "<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="< 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."); diff --git a/src/server.h b/src/server.h index e71a811ea..28678f59c 100644 --- a/src/server.h +++ b/src/server.h @@ -55,23 +55,6 @@ class ServerEnvironment; struct SimpleSoundSpec; -class ServerError : public std::exception -{ -public: - ServerError(const std::string &s) - { - m_s = "ServerError: "; - m_s += s; - } - virtual ~ServerError() throw() - {} - virtual const char * what() const throw() - { - return m_s.c_str(); - } - std::string m_s; -}; - /* Some random functions */