summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSalvatore Sanfilippo <antirez@gmail.com>2020-03-25 12:44:26 +0100
committerGitHub <noreply@github.com>2020-03-25 12:44:26 +0100
commit643bc48a00612d37a1e3efbf288cb80d7817bb2d (patch)
tree8e3b891b592322fcdd568b79bb0b56138ab88229
parentc80d81c80aa4421f48d9e3fd005ca82546d82239 (diff)
parentec007559ff703d27916f54ad0a41d154a88d9ac4 (diff)
downloadredis-643bc48a00612d37a1e3efbf288cb80d7817bb2d.tar.gz
Merge pull request #7022 from oranagra/multi-busy-script
MULTI/EXEC during LUA script timeout are messed up
-rw-r--r--src/server.c1
-rw-r--r--tests/unit/multi.tcl72
2 files changed, 73 insertions, 0 deletions
diff --git a/src/server.c b/src/server.c
index ddc90b3dd..5a54a3abb 100644
--- a/src/server.c
+++ b/src/server.c
@@ -3553,6 +3553,7 @@ int processCommand(client *c) {
c->cmd->proc != authCommand &&
c->cmd->proc != helloCommand &&
c->cmd->proc != replconfCommand &&
+ c->cmd->proc != multiCommand && c->cmd->proc != execCommand && c->cmd->proc != discardCommand &&
!(c->cmd->proc == shutdownCommand &&
c->argc == 2 &&
tolower(((char*)c->argv[1]->ptr)[0]) == 'n') &&
diff --git a/tests/unit/multi.tcl b/tests/unit/multi.tcl
index 9fcef71d6..55f18bec8 100644
--- a/tests/unit/multi.tcl
+++ b/tests/unit/multi.tcl
@@ -320,4 +320,76 @@ start_server {tags {"multi"}} {
$rd close
r ping
} {PONG}
+
+ test {MULTI and script timeout} {
+ # check that if MULTI arrives during timeout, it is either refused, or
+ # allowed to pass, and we don't end up executing half of the transaction
+ set rd1 [redis_deferring_client]
+ set rd2 [redis_deferring_client]
+ r config set lua-time-limit 10
+ r set xx 1
+ $rd1 eval {while true do end} 0
+ after 200
+ catch { $rd2 multi; $rd2 read } e
+ catch { $rd2 incr xx; $rd2 read } e
+ r script kill
+ after 200 ; # Give some time to Lua to call the hook again...
+ catch { $rd2 incr xx; $rd2 read } e
+ catch { $rd2 exec; $rd2 read } e
+ set xx [r get xx]
+ # make sure that either the whole transcation passed or none of it (we actually expect none)
+ assert { $xx == 1 || $xx == 3}
+ # check that the connection is no longer in multi state
+ $rd2 ping asdf
+ set pong [$rd2 read]
+ assert_equal $pong "asdf"
+ }
+
+ test {EXEC and script timeout} {
+ # check that if EXEC arrives during timeout, we don't end up executing
+ # half of the transaction, and also that we exit the multi state
+ set rd1 [redis_deferring_client]
+ set rd2 [redis_deferring_client]
+ r config set lua-time-limit 10
+ r set xx 1
+ catch { $rd2 multi; $rd2 read } e
+ catch { $rd2 incr xx; $rd2 read } e
+ $rd1 eval {while true do end} 0
+ after 200
+ catch { $rd2 incr xx; $rd2 read } e
+ catch { $rd2 exec; $rd2 read } e
+ r script kill
+ after 200 ; # Give some time to Lua to call the hook again...
+ set xx [r get xx]
+ # make sure that either the whole transcation passed or none of it (we actually expect none)
+ assert { $xx == 1 || $xx == 3}
+ # check that the connection is no longer in multi state
+ $rd2 ping asdf
+ set pong [$rd2 read]
+ assert_equal $pong "asdf"
+ }
+
+ test {MULTI-EXEC body and script timeout} {
+ # check that we don't run an imcomplete transaction due to some commands
+ # arriving during busy script
+ set rd1 [redis_deferring_client]
+ set rd2 [redis_deferring_client]
+ r config set lua-time-limit 10
+ r set xx 1
+ catch { $rd2 multi; $rd2 read } e
+ catch { $rd2 incr xx; $rd2 read } e
+ $rd1 eval {while true do end} 0
+ after 200
+ catch { $rd2 incr xx; $rd2 read } e
+ r script kill
+ after 200 ; # Give some time to Lua to call the hook again...
+ catch { $rd2 exec; $rd2 read } e
+ set xx [r get xx]
+ # make sure that either the whole transcation passed or none of it (we actually expect none)
+ assert { $xx == 1 || $xx == 3}
+ # check that the connection is no longer in multi state
+ $rd2 ping asdf
+ set pong [$rd2 read]
+ assert_equal $pong "asdf"
+ }
}