summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsrzhao <srzhao@sysnew.com>2020-01-20 21:17:02 +0800
committerantirez <antirez@gmail.com>2020-04-23 16:06:21 +0200
commit0efb93d0c00b20ca87b18a92484225a54614aef6 (patch)
treefa01d3959ae55aa1a24196299bb6f3ab25e377a2
parentce878b6ed5df1a7b3e87a8af2d1262de4c5bb828 (diff)
downloadredis-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.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 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;