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>
This commit is contained in:
zyxwvu Shi 2021-04-22 13:59:10 +08:00 committed by GitHub
parent 63acfe4b00
commit f61c37cec9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 10 additions and 6 deletions

View File

@ -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

View File

@ -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();
}
}

View File

@ -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