diff --git a/games/minimal/mods/errorhandler_test/init.lua b/games/minimal/mods/errorhandler_test/init.lua new file mode 100644 index 000000000..9d1535c1d --- /dev/null +++ b/games/minimal/mods/errorhandler_test/init.lua @@ -0,0 +1,106 @@ +-- +-- exception handler test module +-- +-- +-- To avoid this from crashing the module will startup in inactive mode. +-- to make specific errors happen you need to cause them by following +-- chat command: +-- +-- exceptiontest +-- +-- location has to be one of: +-- * mapgen: cause in next on_generate call +-- * entity_step: spawn a entity and make it do error in on_step +-- * globalstep: do error in next globalstep +-- * immediate: cause right in chat handler +-- +-- errortypes defined are: +-- * segv: make sigsegv happen +-- * zerodivision: cause a division by zero to happen +-- * exception: throw an exception + +if core.cause_error == nil or + type(core.cause_error) ~= "function" then + return +end + + +core.log("action", "WARNING: loading exception handler test module!") + +local exceptiondata = { + tocause = "none", + mapgen = false, + entity_step = false, + globalstep = false, +} + +local exception_entity = +{ + on_step = function(self, dtime) + if exceptiondata.entity_step then + core.cause_error(exceptiondata.tocause) + end + end, +} +local exception_entity_name = "errorhandler_test:error_entity" + +local function exception_chat_handler(playername, param) + local parameters = param:split(" ") + + if #parameters ~= 2 then + core.chat_send_player(playername, "Invalid argument count for exceptiontest") + end + + core.log("error", "Causing error at:" .. parameters[1]) + + if parameters[1] == "mapgen" then + exceptiondata.tocause = parameters[2] + exceptiondata.mapgen = true + elseif parameters[1] == "entity_step" then + --spawn entity at player location + local player = core.get_player_by_name(playername) + + if player:is_player() then + local pos = player:getpos() + + core.add_entity(pos, exception_entity_name) + end + + exceptiondata.tocause = parameters[2] + exceptiondata.entity_step = true + + elseif parameters[1] == "globalstep" then + exceptiondata.tocause = parameters[2] + exceptiondata.globalstep = true + + elseif parameters[1] == "immediate" then + core.cause_error(parameters[2]) + + else + core.chat_send_player(playername, "Invalid error location: " .. dump(parameters[1])) + end +end + +core.register_chatcommand("exceptiontest", + { + params = " ", + description = "cause a given error to happen.\n" .. + " location=(mapgen,entity_step,globalstep,immediate)\n" .. + " errortype=(segv,zerodivision,exception)", + func = exception_chat_handler, + privs = { server=true } + }) + +core.register_globalstep(function(dtime) + if exceptiondata.globalstep then + core.cause_error(exceptiondata.tocause) + end +end) + +core.register_on_generated(function(minp, maxp, blockseed) + if exceptiondata.mapgen then + core.cause_error(exceptiondata.tocause) + end +end) + +core.register_entity(exception_entity_name, exception_entity) diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp index 76fe439eb..8d7f6512e 100644 --- a/src/script/lua_api/l_server.cpp +++ b/src/script/lua_api/l_server.cpp @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "server.h" #include "environment.h" #include "player.h" +#include "log.h" // request_shutdown() int ModApiServer::l_request_shutdown(lua_State *L) @@ -449,6 +450,36 @@ int ModApiServer::l_notify_authentication_modified(lua_State *L) return 0; } +#ifndef NDEBUG +// cause_error(type_of_error) +int ModApiServer::l_cause_error(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + std::string type_of_error = "none"; + if(lua_isstring(L, 1)) + type_of_error = lua_tostring(L, 1); + + errorstream << "Error handler test called, errortype=" << type_of_error << std::endl; + + if(type_of_error == "segv") { + volatile int* some_pointer = 0; + errorstream << "Cause a sigsegv now: " << (*some_pointer) << std::endl; + + } else if (type_of_error == "zerodivision") { + + unsigned int some_number = porting::getTimeS(); + unsigned int zerovalue = 0; + unsigned int result = some_number / zerovalue; + errorstream << "Well this shouldn't ever be shown: " << result << std::endl; + + } else if (type_of_error == "exception") { + throw BaseException("Errorhandler test fct called"); + } + + return 0; +} +#endif + void ModApiServer::Initialize(lua_State *L, int top) { API_FCT(request_shutdown); @@ -475,4 +506,8 @@ void ModApiServer::Initialize(lua_State *L, int top) API_FCT(kick_player); API_FCT(unban_player_or_ip); API_FCT(notify_authentication_modified); + +#ifndef NDEBUG + API_FCT(cause_error); +#endif } diff --git a/src/script/lua_api/l_server.h b/src/script/lua_api/l_server.h index 4101f2856..fd85a8975 100644 --- a/src/script/lua_api/l_server.h +++ b/src/script/lua_api/l_server.h @@ -88,6 +88,11 @@ private: // notify_authentication_modified(name) static int l_notify_authentication_modified(lua_State *L); +#ifndef NDEBUG + // cause_error(type_of_error) + static int l_cause_error(lua_State *L); +#endif + public: static void Initialize(lua_State *L, int top);