Set LUA_MASKCOUNT hook more selectively. Fixes issue #480.

An user reported a crash with Redis scripting (see issue #480 on
github), inspection of the kindly provided strack trace showed that
server.lua_caller was probably set to NULL. The stack trace also slowed
that the call to the hook was originating from a point where we just
used to set/get a few global variables in the Lua state.

What was happening is that we did not set the timeout hook selectively
only when the user script was called. Now we set it more selectively,
specifically only in the context of the lua_pcall() call, and make sure
to remove the hook when the call returns. Otherwise the hook can get
called in random contexts every time we do something with the Lua
state.
This commit is contained in:
antirez 2012-04-27 11:41:25 +02:00
parent a3eb7ac87d
commit 0ad10db220

View File

@ -716,6 +716,7 @@ void evalGenericCommand(redisClient *c, int evalsha) {
lua_State *lua = server.lua;
char funcname[43];
long long numkeys;
int delhook = 0;
/* We want the same PRNG sequence at every call so that our PRNG is
* not affected by external state. */
@ -786,19 +787,19 @@ void evalGenericCommand(redisClient *c, int evalsha) {
* is running for too much time.
* We set the hook only if the time limit is enabled as the hook will
* make the Lua script execution slower. */
server.lua_caller = c;
server.lua_time_start = ustime()/1000;
server.lua_kill = 0;
if (server.lua_time_limit > 0 && server.masterhost == NULL) {
lua_sethook(lua,luaMaskCountHook,LUA_MASKCOUNT,100000);
} else {
lua_sethook(lua,luaMaskCountHook,0,0);
delhook = 1;
}
/* At this point whatever this script was never seen before or if it was
* already defined, we can call it. We have zero arguments and expect
* a single return value. */
server.lua_caller = c;
server.lua_time_start = ustime()/1000;
server.lua_kill = 0;
if (lua_pcall(lua,0,1,0)) {
if (delhook) lua_sethook(lua,luaMaskCountHook,0,0); /* Disable hook */
if (server.lua_timedout) {
server.lua_timedout = 0;
/* Restore the readable handler that was unregistered when the
@ -814,6 +815,7 @@ void evalGenericCommand(redisClient *c, int evalsha) {
lua_gc(lua,LUA_GCCOLLECT,0);
return;
}
if (delhook) lua_sethook(lua,luaMaskCountHook,0,0); /* Disable hook */
server.lua_timedout = 0;
server.lua_caller = NULL;
selectDb(c,server.lua_client->db->id); /* set DB ID from Lua client */