Unverified Commit b7289e91 authored by valentinogeron's avatar valentinogeron Committed by GitHub
Browse files

EXEC with only read commands should not be rejected when OOM (#7696)

If the server gets MULTI command followed by only read
commands, and right before it gets the EXEC it reaches OOM,
the client will get OOM response.

So, from now on, it will get OOM response only if there was
at least one command that was tagged with `use-memory` flag
parent daef1f00
...@@ -3625,14 +3625,19 @@ int processCommand(client *c) { ...@@ -3625,14 +3625,19 @@ int processCommand(client *c) {
* into a slave, that may be the active client, to be freed. */ * into a slave, that may be the active client, to be freed. */
if (server.current_client == NULL) return C_ERR; if (server.current_client == NULL) return C_ERR;
/* It was impossible to free enough memory, and the command the client int reject_cmd_on_oom = is_denyoom_command;
* is trying to execute is denied during OOM conditions or the client /* If client is in MULTI/EXEC context, queuing may consume an unlimited
* is in MULTI/EXEC context? Error. */ * amount of memory, so we want to stop that.
if (out_of_memory && * However, we never want to reject DISCARD, or even EXEC (unless it
(is_denyoom_command || * contains denied commands, in which case is_denyoom_command is already
(c->flags & CLIENT_MULTI && * set. */
c->cmd->proc != discardCommand))) if (c->flags & CLIENT_MULTI &&
{ c->cmd->proc != execCommand &&
c->cmd->proc != discardCommand) {
reject_cmd_on_oom = 1;
}
if (out_of_memory && reject_cmd_on_oom) {
rejectCommand(c, shared.oomerr); rejectCommand(c, shared.oomerr);
return C_OK; return C_OK;
} }
......
...@@ -466,4 +466,42 @@ start_server {tags {"multi"}} { ...@@ -466,4 +466,42 @@ start_server {tags {"multi"}} {
assert { $xx == 1 } assert { $xx == 1 }
$r1 close; $r1 close;
} }
test {EXEC with only read commands should not be rejected when OOM} {
set r2 [redis_client]
r set x value
r multi
r get x
r ping
# enforcing OOM
$r2 config set maxmemory 1
# finish the multi transaction with exec
assert { [r exec] == {value PONG} }
# releasing OOM
$r2 config set maxmemory 0
$r2 close
}
test {EXEC with at least one use-memory command should fail} {
set r2 [redis_client]
r multi
r set x 1
r get x
# enforcing OOM
$r2 config set maxmemory 1
# finish the multi transaction with exec
catch {r exec} e
assert_match {EXECABORT*OOM*} $e
# releasing OOM
$r2 config set maxmemory 0
$r2 close
}
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment