summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2018-09-05 15:48:08 +0200
committerantirez <antirez@gmail.com>2018-09-05 15:48:08 +0200
commit7e11825ef4467ccc64f961761ea050a3df4853ba (patch)
tree2afbdd609085e40831395614ef0d60615d7c84a0
parent092e4de613af1464d7592cd51e12bd1c87dd0645 (diff)
downloadredis-7e11825ef4467ccc64f961761ea050a3df4853ba.tar.gz
Safer script stop condition on OOM.
Here the idea is that we do not want freeMemoryIfNeeded() to propagate a DEL command before the script and change what happens in the script execution once it reaches the slave. For example see this potential issue (in the words of @soloestoy): On master, we run the following script: if redis.call('get','key') then redis.call('set','xxx','yyy') end redis.call('set','c','d') Then when redis attempts to execute redis.call('set','xxx','yyy'), we call freeMemoryIfNeeded(), and the key may get deleted, and because redis.call('set','xxx','yyy') has already been executed on master, this script will be replicated to slave. But the slave received "DEL key" before the script, and will ignore maxmemory, so after that master has xxx and c, slave has only one key c. Note that this patch (and other related work) was authored collaboratively in issue #5250 with the help of @soloestoy and @oranagra. Related to issue #5250.
-rw-r--r--src/scripting.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/src/scripting.c b/src/scripting.c
index 4b5b0002f..43f8d09a5 100644
--- a/src/scripting.c
+++ b/src/scripting.c
@@ -512,10 +512,13 @@ int luaRedisGenericCommand(lua_State *lua, int raise_error) {
* could enlarge the memory usage are not allowed, but only if this is the
* first write in the context of this script, otherwise we can't stop
* in the middle. */
- if (server.maxmemory && server.lua_write_dirty == 0 &&
+ if (server.maxmemory && /* Maxmemory is actually enabled. */
+ !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. */
(cmd->flags & CMD_DENYOOM))
{
- if (freeMemoryIfNeeded() == C_ERR) {
+ if (getMaxmemoryState(NULL,NULL,NULL,NULL) != C_OK) {
luaPushError(lua, shared.oomerr->ptr);
goto cleanup;
}