diff options
author | srzhao <srzhao@sysnew.com> | 2020-01-20 21:17:02 +0800 |
---|---|---|
committer | srzhao <srzhao@sysnew.com> | 2020-01-20 21:34:05 +0800 |
commit | 38f6207f884f514e928513acb6560fdb375daa2e (patch) | |
tree | 19724330415bfeb7fee0fe522300ffd0b080b594 | |
parent | 7ef2270ee73e75b00b0c1bde40fb1df55c7ec6ff (diff) | |
download | redis-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.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 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; |