mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 10:03:45 +01:00
Fix server crashing on Lua errors
Previously, the server called FATAL_ERROR when a Lua error occured. This caused a (mostly useless) core dump. The server now simply throws an exception, which is caught and printed before exiting with a non-zero return value. This also fixes a number of instances where errors were logged multiple times.
This commit is contained in:
parent
b872df6ef6
commit
9269a0ecc7
@ -125,6 +125,12 @@ public:
|
|||||||
PrngException(std::string s): BaseException(s) {}
|
PrngException(std::string s): BaseException(s) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ModError : public BaseException {
|
||||||
|
public:
|
||||||
|
ModError(const std::string &s): BaseException(s) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Some "old-style" interrupts:
|
Some "old-style" interrupts:
|
||||||
*/
|
*/
|
||||||
|
@ -238,13 +238,13 @@ bool GUIEngine::loadMainMenuScript()
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string script = porting::path_share + DIR_DELIM "builtin" + DIR_DELIM "init.lua";
|
std::string script = porting::path_share + DIR_DELIM "builtin" + DIR_DELIM "init.lua";
|
||||||
if (m_script->loadScript(script)) {
|
try {
|
||||||
|
m_script->loadScript(script);
|
||||||
// Menu script loaded
|
// Menu script loaded
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} catch (const ModError &e) {
|
||||||
infostream
|
errorstream << "GUIEngine: execution of menu script failed: "
|
||||||
<< "GUIEngine: execution of menu script in: \""
|
<< e.what() << std::endl;
|
||||||
<< m_scriptdir << "\" failed!" << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -816,6 +816,7 @@ static bool run_dedicated_server(const GameParams &game_params, const Settings &
|
|||||||
if (cmd_args.exists("migrate"))
|
if (cmd_args.exists("migrate"))
|
||||||
return migrate_database(game_params, cmd_args);
|
return migrate_database(game_params, cmd_args);
|
||||||
|
|
||||||
|
try {
|
||||||
// Create server
|
// Create server
|
||||||
Server server(game_params.world_path, game_params.game_spec, false,
|
Server server(game_params.world_path, game_params.game_spec, false,
|
||||||
bind_addr.isIPv6());
|
bind_addr.isIPv6());
|
||||||
@ -824,6 +825,13 @@ static bool run_dedicated_server(const GameParams &game_params, const Settings &
|
|||||||
// Run server
|
// Run server
|
||||||
bool &kill = *porting::signal_handler_killstatus();
|
bool &kill = *porting::signal_handler_killstatus();
|
||||||
dedicated_server_loop(server, kill);
|
dedicated_server_loop(server, kill);
|
||||||
|
} catch (const ModError &e) {
|
||||||
|
errorstream << "ModError: " << e.what() << std::endl;
|
||||||
|
return false;
|
||||||
|
} catch (const ServerError &e) {
|
||||||
|
errorstream << "ServerError: " << e.what() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "strfnd.h"
|
#include "strfnd.h"
|
||||||
#include "convert_json.h"
|
#include "convert_json.h"
|
||||||
|
#include "exceptions.h"
|
||||||
|
|
||||||
static bool parseDependsLine(std::istream &is,
|
static bool parseDependsLine(std::istream &is,
|
||||||
std::string &dep, std::set<char> &symbols)
|
std::string &dep, std::set<char> &symbols)
|
||||||
|
18
src/mods.h
18
src/mods.h
@ -26,29 +26,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <exception>
|
|
||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#define MODNAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyz0123456789_"
|
#define MODNAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyz0123456789_"
|
||||||
|
|
||||||
class ModError : public std::exception
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ModError(const std::string &s)
|
|
||||||
{
|
|
||||||
m_s = "ModError: ";
|
|
||||||
m_s += s;
|
|
||||||
}
|
|
||||||
virtual ~ModError() throw()
|
|
||||||
{}
|
|
||||||
virtual const char * what() const throw()
|
|
||||||
{
|
|
||||||
return m_s.c_str();
|
|
||||||
}
|
|
||||||
std::string m_s;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ModSpec
|
struct ModSpec
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
|
@ -52,10 +52,10 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class LuaError : public ServerError
|
class LuaError : public ModError
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LuaError(const std::string &s) : ServerError(s) {}
|
LuaError(const std::string &s) : ModError(s) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -243,8 +243,12 @@ void* AsyncWorkerThread::run()
|
|||||||
lua_State *L = getStack();
|
lua_State *L = getStack();
|
||||||
|
|
||||||
std::string script = getServer()->getBuiltinLuaPath() + DIR_DELIM + "init.lua";
|
std::string script = getServer()->getBuiltinLuaPath() + DIR_DELIM + "init.lua";
|
||||||
if (!loadScript(script)) {
|
try {
|
||||||
FATAL_ERROR("execution of async base environment failed!");
|
loadScript(script);
|
||||||
|
} catch (const ModError &e) {
|
||||||
|
errorstream << "Execution of async base environment failed: "
|
||||||
|
<< e.what() << std::endl;
|
||||||
|
FATAL_ERROR("Execution of async base environment failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
int error_handler = PUSH_ERROR_HANDLER(L);
|
int error_handler = PUSH_ERROR_HANDLER(L);
|
||||||
|
@ -119,15 +119,15 @@ ScriptApiBase::~ScriptApiBase()
|
|||||||
lua_close(m_luastack);
|
lua_close(m_luastack);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScriptApiBase::loadMod(const std::string &script_path,
|
void ScriptApiBase::loadMod(const std::string &script_path,
|
||||||
const std::string &mod_name, std::string *error)
|
const std::string &mod_name)
|
||||||
{
|
{
|
||||||
ModNameStorer mod_name_storer(getStack(), mod_name);
|
ModNameStorer mod_name_storer(getStack(), mod_name);
|
||||||
|
|
||||||
return loadScript(script_path, error);
|
loadScript(script_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScriptApiBase::loadScript(const std::string &script_path, std::string *error)
|
void ScriptApiBase::loadScript(const std::string &script_path)
|
||||||
{
|
{
|
||||||
verbosestream << "Loading and running script from " << script_path << std::endl;
|
verbosestream << "Loading and running script from " << script_path << std::endl;
|
||||||
|
|
||||||
@ -144,17 +144,11 @@ bool ScriptApiBase::loadScript(const std::string &script_path, std::string *erro
|
|||||||
ok = ok && !lua_pcall(L, 0, 0, error_handler);
|
ok = ok && !lua_pcall(L, 0, 0, error_handler);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
std::string error_msg = lua_tostring(L, -1);
|
std::string error_msg = lua_tostring(L, -1);
|
||||||
if (error)
|
lua_pop(L, 2); // Pop error message and error handler
|
||||||
*error = error_msg;
|
throw ModError("Failed to load and run script from " +
|
||||||
errorstream << "========== ERROR FROM LUA ===========" << std::endl
|
script_path + ":\n" + error_msg);
|
||||||
<< "Failed to load and run script from " << std::endl
|
|
||||||
<< script_path << ":" << std::endl << std::endl
|
|
||||||
<< error_msg << std::endl << std::endl
|
|
||||||
<< "======= END OF ERROR FROM LUA ========" << std::endl;
|
|
||||||
lua_pop(L, 1); // Pop error message from stack
|
|
||||||
}
|
}
|
||||||
lua_pop(L, 1); // Pop error handler
|
lua_pop(L, 1); // Pop error handler
|
||||||
return ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push the list of callbacks (a lua table).
|
// Push the list of callbacks (a lua table).
|
||||||
|
@ -63,9 +63,9 @@ public:
|
|||||||
ScriptApiBase();
|
ScriptApiBase();
|
||||||
virtual ~ScriptApiBase();
|
virtual ~ScriptApiBase();
|
||||||
|
|
||||||
bool loadMod(const std::string &script_path, const std::string &mod_name,
|
// These throw a ModError on failure
|
||||||
std::string *error=NULL);
|
void loadMod(const std::string &script_path, const std::string &mod_name);
|
||||||
bool loadScript(const std::string &script_path, std::string *error=NULL);
|
void loadScript(const std::string &script_path);
|
||||||
|
|
||||||
void runCallbacksRaw(int nargs,
|
void runCallbacksRaw(int nargs,
|
||||||
RunCallbacksMode mode, const char *fxn);
|
RunCallbacksMode mode, const char *fxn);
|
||||||
|
@ -276,11 +276,8 @@ Server::Server(
|
|||||||
m_script = new GameScripting(this);
|
m_script = new GameScripting(this);
|
||||||
|
|
||||||
std::string script_path = getBuiltinLuaPath() + DIR_DELIM "init.lua";
|
std::string script_path = getBuiltinLuaPath() + DIR_DELIM "init.lua";
|
||||||
std::string error_msg;
|
|
||||||
|
|
||||||
if (!m_script->loadMod(script_path, BUILTIN_MOD_NAME, &error_msg))
|
m_script->loadMod(script_path, BUILTIN_MOD_NAME);
|
||||||
throw ModError("Failed to load and run " + script_path
|
|
||||||
+ "\nError from Lua:\n" + error_msg);
|
|
||||||
|
|
||||||
// Print mods
|
// Print mods
|
||||||
infostream << "Server: Loading mods: ";
|
infostream << "Server: Loading mods: ";
|
||||||
@ -291,26 +288,18 @@ Server::Server(
|
|||||||
}
|
}
|
||||||
infostream << std::endl;
|
infostream << std::endl;
|
||||||
// Load and run "mod" scripts
|
// Load and run "mod" scripts
|
||||||
for (std::vector<ModSpec>::iterator i = m_mods.begin();
|
for (std::vector<ModSpec>::iterator it = m_mods.begin();
|
||||||
i != m_mods.end(); ++i) {
|
it != m_mods.end(); ++it) {
|
||||||
const ModSpec &mod = *i;
|
const ModSpec &mod = *it;
|
||||||
if (!string_allowed(mod.name, MODNAME_ALLOWED_CHARS)) {
|
if (!string_allowed(mod.name, MODNAME_ALLOWED_CHARS)) {
|
||||||
std::ostringstream err;
|
throw ModError("Error loading mod \"" + mod.name +
|
||||||
err << "Error loading mod \"" << mod.name
|
"\": Mod name does not follow naming conventions: "
|
||||||
<< "\": mod_name does not follow naming conventions: "
|
"Only chararacters [a-z0-9_] are allowed.");
|
||||||
<< "Only chararacters [a-z0-9_] are allowed." << std::endl;
|
|
||||||
errorstream << err.str().c_str();
|
|
||||||
throw ModError(err.str());
|
|
||||||
}
|
}
|
||||||
std::string script_path = mod.path + DIR_DELIM "init.lua";
|
std::string script_path = mod.path + DIR_DELIM + "init.lua";
|
||||||
infostream << " [" << padStringRight(mod.name, 12) << "] [\""
|
infostream << " [" << padStringRight(mod.name, 12) << "] [\""
|
||||||
<< script_path << "\"]" << std::endl;
|
<< script_path << "\"]" << std::endl;
|
||||||
if (!m_script->loadMod(script_path, mod.name, &error_msg)) {
|
m_script->loadMod(script_path, mod.name);
|
||||||
errorstream << "Server: Failed to load and run "
|
|
||||||
<< script_path << std::endl;
|
|
||||||
throw ModError("Failed to load and run " + script_path
|
|
||||||
+ "\nError from Lua:\n" + error_msg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read Textures and calculate sha1 sums
|
// Read Textures and calculate sha1 sums
|
||||||
@ -491,19 +480,13 @@ void Server::step(float dtime)
|
|||||||
}
|
}
|
||||||
// Throw if fatal error occurred in thread
|
// Throw if fatal error occurred in thread
|
||||||
std::string async_err = m_async_fatal_error.get();
|
std::string async_err = m_async_fatal_error.get();
|
||||||
if(async_err != "") {
|
if (!async_err.empty()) {
|
||||||
if (m_simple_singleplayer_mode) {
|
if (!m_simple_singleplayer_mode) {
|
||||||
throw ServerError(async_err);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m_env->kickAllPlayers(SERVER_ACCESSDENIED_CRASH,
|
m_env->kickAllPlayers(SERVER_ACCESSDENIED_CRASH,
|
||||||
g_settings->get("kick_msg_crash"),
|
g_settings->get("kick_msg_crash"),
|
||||||
g_settings->getBool("ask_reconnect_on_crash"));
|
g_settings->getBool("ask_reconnect_on_crash"));
|
||||||
errorstream << "UNRECOVERABLE error occurred. Stopping server. "
|
|
||||||
<< "Please fix the following error:" << std::endl
|
|
||||||
<< async_err << std::endl;
|
|
||||||
FATAL_ERROR(async_err.c_str());
|
|
||||||
}
|
}
|
||||||
|
throw ServerError(async_err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user