Skip to content

Commit aa88453

Browse files
li-bensonyoungmore1024zuiderkwast
authored
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 5abaf33 commit aa88453

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

src/db.c

+1-1
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

+22
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)