From 77a75fdef5c56033e328252f47bf3a26a3dab1b4 Mon Sep 17 00:00:00 2001 From: antirez Date: Fri, 27 Apr 2012 11:41:25 +0200 Subject: [PATCH] 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. --- src/scripting.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/scripting.c b/src/scripting.c index a5f5683e..8c89c923 100644 --- a/src/scripting.c +++ b/src/scripting.c @@ -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 */ -- 2.47.2