summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzyxwvu Shi <imzyxwvu@live.com>2021-04-22 13:59:10 +0800
committerOran Agra <oran@redislabs.com>2021-05-03 22:57:00 +0300
commit6384fe341472598eee92439fc16b088706fa54f3 (patch)
tree209b2f509de382add1894df753fd09a7cd53a4d7
parentef64333e6390653e6bbdedf18c60cc3449bbd5a1 (diff)
downloadredis-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.c2
-rw-r--r--src/scripting.c11
-rw-r--r--src/server.h3
3 files changed, 10 insertions, 6 deletions
diff --git a/src/db.c b/src/db.c
index 40377ec3f..840e95e21 100644
--- a/src/db.c
+++ b/src/db.c
@@ -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