diff options
author | zyxwvu Shi <imzyxwvu@live.com> | 2021-04-22 13:59:10 +0800 |
---|---|---|
committer | Oran Agra <oran@redislabs.com> | 2021-05-03 22:57:00 +0300 |
commit | 6384fe341472598eee92439fc16b088706fa54f3 (patch) | |
tree | 209b2f509de382add1894df753fd09a7cd53a4d7 | |
parent | ef64333e6390653e6bbdedf18c60cc3449bbd5a1 (diff) | |
download | redis-6384fe341472598eee92439fc16b088706fa54f3.tar.gz |
Use monotonic clock to check for Lua script timeout. (#8812)
This prevents a case where NTP moves the system clock
forward resulting in a false detection of a busy script.
Signed-off-by: zyxwvu Shi <i@shiyc.cn>
(cherry picked from commit f61c37cec900ba391541f20f7655aad44a26bafc)
-rw-r--r-- | src/db.c | 2 | ||||
-rw-r--r-- | src/scripting.c | 11 | ||||
-rw-r--r-- | src/server.h | 3 |
3 files changed, 10 insertions, 6 deletions
@@ -1480,7 +1480,7 @@ int keyIsExpired(redisDb *db, robj *key) { * script execution, making propagation to slaves / AOF consistent. * See issue #1525 on Github for more information. */ if (server.lua_caller) { - now = server.lua_time_start; + now = server.lua_time_snapshot; } /* If we are in the middle of a command execution, we still want to use * a reference time that does not change: in that case we just use the diff --git a/src/scripting.c b/src/scripting.c index 299e60810..dbbd50eaf 100644 --- a/src/scripting.c +++ b/src/scripting.c @@ -31,6 +31,7 @@ #include "sha1.h" #include "rand.h" #include "cluster.h" +#include "monotonic.h" #include <lua.h> #include <lauxlib.h> @@ -1427,7 +1428,7 @@ sds luaCreateFunction(client *c, lua_State *lua, robj *body) { /* This is the Lua script "count" hook that we use to detect scripts timeout. */ void luaMaskCountHook(lua_State *lua, lua_Debug *ar) { - long long elapsed = mstime() - server.lua_time_start; + long long elapsed = elapsedMs(server.lua_time_start); UNUSED(ar); UNUSED(lua); @@ -1578,7 +1579,8 @@ void evalGenericCommand(client *c, int evalsha) { server.in_eval = 1; server.lua_caller = c; server.lua_cur_script = funcname + 2; - server.lua_time_start = mstime(); + server.lua_time_start = getMonotonicUs(); + server.lua_time_snapshot = mstime(); server.lua_kill = 0; if (server.lua_time_limit > 0 && ldb.active == 0) { lua_sethook(lua,luaMaskCountHook,LUA_MASKCOUNT,100000); @@ -2729,7 +2731,7 @@ void luaLdbLineHook(lua_State *lua, lua_Debug *ar) { /* Check if a timeout occurred. */ if (ar->event == LUA_HOOKCOUNT && ldb.step == 0 && bp == 0) { - mstime_t elapsed = mstime() - server.lua_time_start; + mstime_t elapsed = elapsedMs(server.lua_time_start); mstime_t timelimit = server.lua_time_limit ? server.lua_time_limit : 5000; if (elapsed >= timelimit) { @@ -2759,6 +2761,7 @@ void luaLdbLineHook(lua_State *lua, lua_Debug *ar) { lua_pushstring(lua, "timeout during Lua debugging with client closing connection"); lua_error(lua); } - server.lua_time_start = mstime(); + server.lua_time_start = getMonotonicUs(); + server.lua_time_snapshot = mstime(); } } diff --git a/src/server.h b/src/server.h index a2a722c6d..9b7e16a0d 100644 --- a/src/server.h +++ b/src/server.h @@ -1571,7 +1571,8 @@ struct redisServer { dict *lua_scripts; /* A dictionary of SHA1 -> Lua scripts */ unsigned long long lua_scripts_mem; /* Cached scripts' memory + oh */ mstime_t lua_time_limit; /* Script timeout in milliseconds */ - mstime_t lua_time_start; /* Start time of script, milliseconds time */ + monotime lua_time_start; /* monotonic timer to detect timed-out script */ + mstime_t lua_time_snapshot; /* Snapshot of mstime when script is started */ int lua_write_dirty; /* True if a write command was called during the execution of the current script. */ int lua_random_dirty; /* True if a random command was called during the |