summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/networking.c10
-rw-r--r--tests/unit/scripting.tcl37
2 files changed, 46 insertions, 1 deletions
diff --git a/src/networking.c b/src/networking.c
index bd0bcadb2..d554d748b 100644
--- a/src/networking.c
+++ b/src/networking.c
@@ -1990,12 +1990,20 @@ void commandProcessed(client *c) {
* of processing the command, otherwise C_OK is returned. */
int processCommandAndResetClient(client *c) {
int deadclient = 0;
+ client *old_client = server.current_client;
server.current_client = c;
if (processCommand(c) == C_OK) {
commandProcessed(c);
}
if (server.current_client == NULL) deadclient = 1;
- server.current_client = NULL;
+ /*
+ * Restore the old client, this is needed because when a script
+ * times out, we will get into this code from processEventsWhileBlocked.
+ * Which will cause to set the server.current_client. If not restored
+ * we will return 1 to our caller which will falsely indicate the client
+ * is dead and will stop reading from its buffer.
+ */
+ server.current_client = old_client;
/* performEvictions may flush slave output buffers. This may
* result in a slave, that may be the active client, to be
* freed. */
diff --git a/tests/unit/scripting.tcl b/tests/unit/scripting.tcl
index 92ca05bdc..0efe34cad 100644
--- a/tests/unit/scripting.tcl
+++ b/tests/unit/scripting.tcl
@@ -640,6 +640,43 @@ start_server {tags {"scripting"}} {
assert_match {*killed by user*} $res
}
+ test {Timedout script does not cause a false dead client} {
+ set rd [redis_deferring_client]
+ r config set lua-time-limit 10
+
+ # senging (in a pipeline):
+ # 1. eval "while 1 do redis.call('ping') end" 0
+ # 2. ping
+ set buf "*3\r\n\$4\r\neval\r\n\$33\r\nwhile 1 do redis.call('ping') end\r\n\$1\r\n0\r\n"
+ append buf "*1\r\n\$4\r\nping\r\n"
+ $rd write $buf
+ $rd flush
+
+ wait_for_condition 50 100 {
+ [catch {r ping} e] == 1
+ } else {
+ fail "Can't wait for script to start running"
+ }
+ catch {r ping} e
+ assert_match {BUSY*} $e
+
+ r script kill
+ wait_for_condition 50 100 {
+ [catch {r ping} e] == 0
+ } else {
+ fail "Can't wait for script to be killed"
+ }
+ assert_equal [r ping] "PONG"
+
+ catch {$rd read} res
+ assert_match {*killed by user*} $res
+
+ set res [$rd read]
+ assert_match {*PONG*} $res
+
+ $rd close
+ }
+
test {Timedout script link is still usable after Lua returns} {
r config set lua-time-limit 10
r eval {for i=1,100000 do redis.call('ping') end return 'ok'} 0