diff options
author | srzhao <srzhao@sysnew.com> | 2020-01-20 21:17:02 +0800 |
---|---|---|
committer | antirez <antirez@gmail.com> | 2020-04-23 16:06:21 +0200 |
commit | 0efb93d0c00b20ca87b18a92484225a54614aef6 (patch) | |
tree | fa01d3959ae55aa1a24196299bb6f3ab25e377a2 | |
parent | ce878b6ed5df1a7b3e87a8af2d1262de4c5bb828 (diff) | |
download | redis-0efb93d0c00b20ca87b18a92484225a54614aef6.tar.gz |
Check OOM at script start to get stable lua OOM state.
Checking OOM by `getMaxMemoryState` inside script might get different result
with `freeMemoryIfNeededAndSafe` at script start, because lua stack and
arguments also consume memory.
This leads to memory `borderline` when memory grows near server.maxmemory:
- `freeMemoryIfNeededAndSafe` at script start detects no OOM, no memory freed
- `getMaxMemoryState` inside script detects OOM, script aborted
We solve this 'borderline' issue by saving OOM state at script start to get
stable lua OOM state.
related to issue #6565 and #5250.
-rw-r--r-- | src/scripting.c | 7 | ||||
-rw-r--r-- | src/server.c | 7 | ||||
-rw-r--r-- | src/server.h | 1 |
3 files changed, 11 insertions, 4 deletions
diff --git a/src/scripting.c b/src/scripting.c index 4dafa327c..1ad781dda 100644 --- a/src/scripting.c +++ b/src/scripting.c @@ -521,12 +521,11 @@ int luaRedisGenericCommand(lua_State *lua, int raise_error) { !server.loading && /* Don't care about mem if loading. */ !server.masterhost && /* Slave must execute the script. */ server.lua_write_dirty == 0 && /* Script had no side effects so far. */ + server.lua_oom && /* Detected OOM when script start. */ (cmd->flags & CMD_DENYOOM)) { - if (getMaxmemoryState(NULL,NULL,NULL,NULL) != C_OK) { - luaPushError(lua, shared.oomerr->ptr); - goto cleanup; - } + luaPushError(lua, shared.oomerr->ptr); + goto cleanup; } if (cmd->flags & CMD_RANDOM) server.lua_random_dirty = 1; diff --git a/src/server.c b/src/server.c index 8a8edbc0b..a61fd82f3 100644 --- a/src/server.c +++ b/src/server.c @@ -2667,6 +2667,13 @@ int processCommand(client *c) { addReply(c, shared.oomerr); return C_OK; } + + /* Save out_of_memory result at script start, otherwise if we check OOM + * untill first write within script, memory used by lua stack and + * arguments might interfere. */ + if (c->cmd->proc == evalCommand || c->cmd->proc == evalShaCommand) { + server.lua_oom = out_of_memory; + } } /* Don't accept write commands if there are problems persisting on disk diff --git a/src/server.h b/src/server.h index f74e8f2f6..9ad603dce 100644 --- a/src/server.h +++ b/src/server.h @@ -1277,6 +1277,7 @@ struct redisServer { execution. */ int lua_kill; /* Kill the script if true. */ int lua_always_replicate_commands; /* Default replication type. */ + int lua_oom; /* OOM detected when script start? */ /* Lazy free */ int lazyfree_lazy_eviction; int lazyfree_lazy_expire; |