Skip to content

Commit 63a6516

Browse files
li-bensonyoungmore1024zuiderkwast
committed
Fix RANDOMKEY infinite loop during CLIENT PAUSE (#1850)
When the `client pause write` is set and all the keys in the server are expired keys, executing the `randomkey` command will lead to an infinite loop. The reason is that expired keys are not deleted in this case. Limit the number of tries and return an expired key after the max number tries in this case. Closes #1848. --------- Signed-off-by: li-benson <[email protected]> Signed-off-by: youngmore <[email protected]> Signed-off-by: Viktor Söderqvist <[email protected]> Co-authored-by: youngmore <[email protected]> Co-authored-by: Viktor Söderqvist <[email protected]>
1 parent a0a7ee3 commit 63a6516

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

src/db.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ robj *dbRandomKey(serverDb *db) {
445445
sds key = objectGetKey(valkey);
446446
robj *keyobj = createStringObject(key, sdslen(key));
447447
if (objectIsExpired(valkey)) {
448-
if (allvolatile && (server.primary_host || server.import_mode) && --maxtries == 0) {
448+
if (allvolatile && (server.primary_host || server.import_mode || isPausedActions(PAUSE_ACTION_EXPIRE)) && --maxtries == 0) {
449449
/* If the DB is composed only of keys with an expire set,
450450
* it could happen that all the keys are already logically
451451
* expired in the replica, so the function cannot stop because

tests/unit/pause.tcl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,28 @@ start_server {tags {"pause network"}} {
412412
} {bar2}
413413
}
414414

415+
test "Test the randomkey command will not cause the server to get into an infinite loop during the client pause write" {
416+
# first, clear the database to avoid interference from existing keys on the test results
417+
r flushall
418+
419+
# then set a key with expire time
420+
r set key value px 3
421+
422+
# set pause-write model and wait key expired
423+
r client pause 10000 write
424+
after 5
425+
426+
wait_for_condition 50 100 {
427+
[r randomkey] == "key"
428+
} else {
429+
fail "execute randomkey failed, caused by the infinite loop"
430+
}
431+
432+
r client unpause
433+
assert_equal [r randomkey] {}
434+
435+
}
436+
415437
# Make sure we unpause at the end
416438
r client unpause
417439
}

0 commit comments

Comments
 (0)