summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorxiaost <xiaost7@gmail.com>2014-09-09 17:53:30 +0800
committerxiaost <xiaost7@gmail.com>2014-09-09 17:53:30 +0800
commitacfc19633dbd522de4571d7ca9cbc629987b39b6 (patch)
treecb1c9e8a1f37fd10f505c0e1be8b5cb00b7fe54d /src
parentb892ea70ae4c2da7a0736943a4ee1915edda838d (diff)
downloadredis-acfc19633dbd522de4571d7ca9cbc629987b39b6.tar.gz
Limit the *SCAN command `dictScan` iterations
*SCAN will cause redis server to hang for seconds after millions of keys was deleted by SCAN/DEL pairs
Diffstat (limited to 'src')
-rw-r--r--src/db.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/src/db.c b/src/db.c
index 8eb1b89a7..d5a381daf 100644
--- a/src/db.c
+++ b/src/db.c
@@ -493,6 +493,11 @@ void scanGenericCommand(redisClient *c, robj *o, unsigned long cursor) {
if (ht) {
void *privdata[2];
+ /* We set the max number of iterations to ten times the specified
+ * COUNT, so if the hash table is in a pathological state (very
+ * sparsely populated) we avoid to block too much time at the cost
+ * of returning no or very few elements. */
+ long maxiterations = count*10;
/* We pass two pointers to the callback: the list to which it will
* add new elements, and the object containing the dictionary so that
@@ -501,7 +506,9 @@ void scanGenericCommand(redisClient *c, robj *o, unsigned long cursor) {
privdata[1] = o;
do {
cursor = dictScan(ht, cursor, scanCallback, privdata);
- } while (cursor && listLength(keys) < (unsigned long)count);
+ } while (cursor &&
+ maxiterations-- &&
+ listLength(keys) < (unsigned long)count);
} else if (o->type == REDIS_SET) {
int pos = 0;
int64_t ll;