client: Get full traceback on lua_pcall() error

This commit is contained in:
Perttu Ahola 2014-09-19 12:51:02 +03:00
parent 2dc409fad9
commit 20cf5c4390
2 changed files with 51 additions and 2 deletions

View File

@ -47,7 +47,7 @@ local function run_in_sandbox(untrusted_code, sandbox)
local untrusted_function, message = loadstring(untrusted_code)
if not untrusted_function then return nil, message end
setfenv(untrusted_function, sandbox)
return pcall(untrusted_function)
return __buildat_pcall(untrusted_function)
end
function buildat:run_script_file(name)
@ -61,7 +61,7 @@ function buildat:run_script_file(name)
--local status, err = run_in_sandbox(
-- [[buildat:Logger("foo"):info("Pihvi")]], sandbox)
if status == false then
log:error("Failed to run script: "..err)
log:error("Failed to run script:\n"..err)
return false
end
return true

View File

@ -279,6 +279,7 @@ struct CApp: public Polycode::EventHandler, public App
DEF_BUILDAT_FUNC(send_packet);
DEF_BUILDAT_FUNC(get_file_content)
DEF_BUILDAT_FUNC(get_path)
DEF_BUILDAT_FUNC(pcall)
ss_ init_lua_path = g_client_config.share_path+"/client/init.lua";
int error = luaL_dofile(L, init_lua_path.c_str());
@ -386,6 +387,54 @@ struct CApp: public Polycode::EventHandler, public App
log_w(MODULE, "Unknown named path: \"%s\"", cs(name));
return 0;
}
static int handle_error(lua_State *L)
{
log_v(MODULE, "handle_error()");
lua_getglobal(L, "debug");
if(!lua_istable(L, -1)){
log_w(MODULE, "handle_error(): debug is nil");
lua_pop(L, 1);
return 1;
}
lua_getfield(L, -1, "traceback");
if(!lua_isfunction(L, -1)){
log_w(MODULE, "handle_error(): debug.traceback is nil");
lua_pop(L, 2);
return 1;
}
lua_pushvalue(L, 1);
lua_pushinteger(L, 2);
lua_call(L, 2, 1);
return 1;
}
// Like lua_pcall, but returns a full traceback on error
// pcall(untrusted_function) -> status, error
static int l_pcall(lua_State *L)
{
log_v(MODULE, "l_pcall()");
lua_pushcfunction(L, handle_error);
int handle_error_stack_i = lua_gettop(L);
lua_pushvalue(L, 1);
int r = lua_pcall(L, 0, 0, handle_error_stack_i);
int error_stack_i = lua_gettop(L);
if(r == 0){
log_v(MODULE, "l_pcall() returned 0 (no error)");
lua_pushboolean(L, true);
return 1;
}
if(r == LUA_ERRRUN)
log_w(MODULE, "pcall(): Runtime error");
if(r == LUA_ERRMEM)
log_w(MODULE, "pcall(): Out of memory");
if(r == LUA_ERRERR)
log_w(MODULE, "pcall(): Error handler failed");
lua_pushboolean(L, false);
lua_pushvalue(L, error_stack_i);
return 2;
}
};
App* createApp(Polycode::PolycodeView *view)