diff --git a/src/server.c b/src/server.c index 838695b88..438325f28 100644 --- a/src/server.c +++ b/src/server.c @@ -4158,7 +4158,7 @@ int processCommand(client *c) { int flags = CMD_CALL_FULL; if (client_reprocessing_command) flags |= CMD_CALL_REPROCESSING; call(c,flags); - if (listLength(server.ready_keys)) + if (listLength(server.ready_keys) && !isInsideYieldingLongCommand()) handleClientsBlockedOnKeys(); } diff --git a/tests/unit/scripting.tcl b/tests/unit/scripting.tcl index cedf2b4f7..c2f79a742 100644 --- a/tests/unit/scripting.tcl +++ b/tests/unit/scripting.tcl @@ -1119,6 +1119,53 @@ start_server {tags {"scripting"}} { r ping } {PONG} + test {Timedout scripts and unblocked command} { + # make sure a command that's allowed during BUSY doesn't trigger an unblocked command + + # enable AOF to also expose an assertion if the bug would happen + r flushall + r config set appendonly yes + + # create clients, and set one to block waiting for key 'x' + set rd [redis_deferring_client] + set rd2 [redis_deferring_client] + set r3 [redis_client] + $rd2 blpop x 0 + wait_for_blocked_clients_count 1 + + # hack: allow the script to use client list command so that we can control when it aborts + r DEBUG set-disable-deny-scripts 1 + r config set lua-time-limit 10 + run_script_on_connection $rd { + local clients + redis.call('lpush',KEYS[1],'y'); + while true do + clients = redis.call('client','list') + if string.find(clients, 'abortscript') ~= nil then break end + end + redis.call('lpush',KEYS[1],'z'); + return clients + } 1 x + + # wait for the script to be busy + after 200 + catch {r ping} e + assert_match {BUSY*} $e + + # run cause the script to abort, and run a command that could have processed + # unblocked clients (due to a bug) + $r3 hello 2 setname abortscript + + # make sure the script completed before the pop was processed + assert_equal [$rd2 read] {x z} + assert_match {*abortscript*} [$rd read] + + $rd close + $rd2 close + $r3 close + r DEBUG set-disable-deny-scripts 0 + } {OK} {external:skip needs:debug} + test {Timedout scripts that modified data can't be killed by SCRIPT KILL} { set rd [redis_deferring_client] r config set lua-time-limit 10