summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsrzhao <srzhao@sysnew.com>2020-01-20 21:17:02 +0800
committersrzhao <srzhao@sysnew.com>2020-01-20 21:34:05 +0800
commit38f6207f884f514e928513acb6560fdb375daa2e (patch)
tree19724330415bfeb7fee0fe522300ffd0b080b594
parent7ef2270ee73e75b00b0c1bde40fb1df55c7ec6ff (diff)
downloadredis-38f6207f884f514e928513acb6560fdb375daa2e.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.c7
-rw-r--r--src/server.c7
-rw-r--r--src/server.h1
3 files changed, 11 insertions, 4 deletions
diff --git a/src/scripting.c b/src/scripting.c
index 9282b7fd9..5ed24ffad 100644
--- a/src/scripting.c
+++ b/src/scripting.c
@@ -655,12 +655,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 2b226f568..21d6aab27 100644
--- a/src/server.c
+++ b/src/server.c
@@ -3442,6 +3442,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;
+ }
}
/* Make sure to use a reasonable amount of memory for client side
diff --git a/src/server.h b/src/server.h
index 8e354c03d..b440beba3 100644
--- a/src/server.h
+++ b/src/server.h
@@ -1376,6 +1376,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;