Made the Lua kernel reentrant by storing the error handler in the registry.

This commit is contained in:
Guillaume Melquiond 2009-03-22 18:59:55 +00:00
parent 036c3f787f
commit abd79952fe

View File

@ -45,6 +45,7 @@ struct event_handler_data
}; };
/* Dummy pointer for getting unique keys for Lua's registry. */ /* Dummy pointer for getting unique keys for Lua's registry. */
static char const executeKey = 0;
static char const gettextKey = 0; static char const gettextKey = 0;
static char const getunitKey = 0; static char const getunitKey = 0;
static char const handlerKey = 0; static char const handlerKey = 0;
@ -581,13 +582,16 @@ LuaKernel::LuaKernel()
lua_pushnil(L); lua_pushnil(L);
lua_setglobal(L, "loadfile"); lua_setglobal(L, "loadfile");
// Push the error handler, then close debug. // Store the error handler, then close debug.
lua_settop(L, 0); lua_pushlightuserdata(L, (void *)&executeKey);
lua_getglobal(L, "debug"); lua_getglobal(L, "debug");
lua_getfield(L, -1, "traceback"); lua_getfield(L, -1, "traceback");
lua_remove(L, -2); lua_remove(L, -2);
lua_settable(L, LUA_REGISTRYINDEX);
lua_pushnil(L); lua_pushnil(L);
lua_setglobal(L, "debug"); lua_setglobal(L, "debug");
lua_settop(L, 0);
} }
LuaKernel::~LuaKernel() LuaKernel::~LuaKernel()
@ -649,13 +653,19 @@ void LuaKernel::execute(char const *prog, int nArgs, int nRets)
{ {
lua_State *L = mState; lua_State *L = mState;
// Load the error handler before the function arguments.
lua_pushlightuserdata(L, (void *)&executeKey);
lua_gettable(L, LUA_REGISTRYINDEX);
if (nArgs)
lua_insert(L, -1 - nArgs);
// Compile script into a variadic function. // Compile script into a variadic function.
int res = luaL_loadstring(L, prog); int res = luaL_loadstring(L, prog);
if (res) if (res)
{ {
std::cerr << "Failure while loading Lua script: " std::cerr << "Failure while loading Lua script: "
<< lua_tostring(L, -1) << '\n'; << lua_tostring(L, -1) << '\n';
lua_pop(L, 1); lua_pop(L, 2);
return; return;
} }
@ -663,12 +673,14 @@ void LuaKernel::execute(char const *prog, int nArgs, int nRets)
if (nArgs) if (nArgs)
lua_insert(L, -1 - nArgs); lua_insert(L, -1 - nArgs);
res = lua_pcall(L, nArgs, nRets, 1); res = lua_pcall(L, nArgs, nRets, -2 - nArgs);
if (res) if (res)
{ {
std::cerr << "Failure while running Lua script: " std::cerr << "Failure while running Lua script: "
<< lua_tostring(L, -1) << '\n'; << lua_tostring(L, -1) << '\n';
lua_pop(L, 1); lua_pop(L, 2);
return; return;
} }
lua_remove(L, -1 - nRets);
} }