mirror of
https://github.com/fluencelabs/redis
synced 2025-03-17 16:10:50 +00:00
Fix infinite loop in dbRandomKey().
Thanks to @kevinmcgehee for signaling the issue and reasoning about the consequences and potential fixes. Issue #5015.
This commit is contained in:
parent
1e92fde3d3
commit
d6e8fe77af
13
src/db.c
13
src/db.c
@ -223,6 +223,8 @@ int dbExists(redisDb *db, robj *key) {
|
||||
* The function makes sure to return keys not already expired. */
|
||||
robj *dbRandomKey(redisDb *db) {
|
||||
dictEntry *de;
|
||||
int maxtries = 100;
|
||||
int allvolatile = dictSize(db->dict) == dictSize(db->expires);
|
||||
|
||||
while(1) {
|
||||
sds key;
|
||||
@ -234,6 +236,17 @@ robj *dbRandomKey(redisDb *db) {
|
||||
key = dictGetKey(de);
|
||||
keyobj = createStringObject(key,sdslen(key));
|
||||
if (dictFind(db->expires,key)) {
|
||||
if (allvolatile && server.masterhost && --maxtries == 0) {
|
||||
/* If the DB is composed only of keys with an expire set,
|
||||
* it could happen that all the keys are already logically
|
||||
* expired in the slave, so the function cannot stop because
|
||||
* expireIfNeeded() is false, nor it can stop because
|
||||
* dictGetRandomKey() returns NULL (there are keys to return).
|
||||
* To prevent the infinite loop we do some tries, but if there
|
||||
* are the conditions for an infinite loop, eventually we
|
||||
* return a key name that may be already expired. */
|
||||
return keyobj;
|
||||
}
|
||||
if (expireIfNeeded(db,keyobj)) {
|
||||
decrRefCount(keyobj);
|
||||
continue; /* search for another key. This expired. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user