From 2c8ae06b6713a6e9af54ec6af0b42ee04507723a Mon Sep 17 00:00:00 2001 From: gms <38031771+guanmengshi@users.noreply.github.com> Date: Tue, 4 Jun 2024 20:16:36 +0800 Subject: [PATCH] Fix crash due to unblock client during slot migration (#13311) In #13224, we found a crash during cluster slot migration but don't know why. So i check all the return C_OK in processCommand to see if we are missing some duration reset and see this. This fix is like #12247, when we reject the command, we should reset the duration. I test it and verify it can fix #13224. So the reason may because we are using stream block and then during the slot migration, it got a redirect and then crash the server. --------- Co-authored-by: debing.sun --- src/server.c | 1 + tests/cluster/tests/15-cluster-slots.tcl | 27 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/server.c b/src/server.c index 4d47b5ed7..5c9870f0e 100644 --- a/src/server.c +++ b/src/server.c @@ -3961,6 +3961,7 @@ int processCommand(client *c) { flagTransaction(c); } clusterRedirectClient(c,n,c->slot,error_code); + c->duration = 0; c->cmd->rejected_calls++; return C_OK; } diff --git a/tests/cluster/tests/15-cluster-slots.tcl b/tests/cluster/tests/15-cluster-slots.tcl index 892e9049b..0f82c78be 100644 --- a/tests/cluster/tests/15-cluster-slots.tcl +++ b/tests/cluster/tests/15-cluster-slots.tcl @@ -60,6 +60,33 @@ test "slot migration is valid from primary to another primary" { assert_equal {OK} [$nodeto(link) cluster setslot $slot node $nodeto(id)] } +test "Client unblocks after slot migration from one primary to another" { + set cluster [redis_cluster 127.0.0.1:[get_instance_attrib redis 0 port]] + set key mystream + set slot [$cluster cluster keyslot $key] + array set nodefrom [$cluster masternode_for_slot $slot] + array set nodeto [$cluster masternode_notfor_slot $slot] + + # Create a stream group on the source node + $nodefrom(link) XGROUP CREATE $key mygroup $ MKSTREAM + + # block another client on xreadgroup + set rd [redis_deferring_client_by_addr $nodefrom(host) $nodefrom(port)] + $rd XREADGROUP GROUP mygroup Alice BLOCK 0 STREAMS $key ">" + wait_for_condition 1000 50 { + [getInfoProperty [$nodefrom(link) info clients] blocked_clients] eq {1} + } else { + fail "client wasn't blocked" + } + + # Start slot migration from the source node to the target node. + # Because the `unblock_on_nokey` option of xreadgroup is set to 1, the client + # will be unblocked when the key `mystream` is migrated. + assert_equal {OK} [$nodefrom(link) CLUSTER SETSLOT $slot MIGRATING $nodeto(id)] + assert_equal {OK} [$nodeto(link) CLUSTER SETSLOT $slot IMPORTING $nodefrom(id)] + $nodefrom(link) MIGRATE $nodeto(host) $nodeto(port) $key 0 5000 +} + test "slot migration is invalid from primary to replica" { set cluster [redis_cluster 127.0.0.1:[get_instance_attrib redis 0 port]] set key order1