diff options
author | Oran Agra <oran@redislabs.com> | 2020-02-05 18:24:14 +0200 |
---|---|---|
committer | Oran Agra <oran@redislabs.com> | 2020-02-06 11:48:12 +0200 |
commit | 28ef18a8946815e0d83a1c0a9b6baf9d27022461 (patch) | |
tree | d607923b20717b8e66229377c9d598079502aff3 /src/dict.c | |
parent | 44ac202fbfbca4210d016c9f77df987b27c1ae4c (diff) | |
download | redis-28ef18a8946815e0d83a1c0a9b6baf9d27022461.tar.gz |
RM_Scan disable dict rehashing
The callback approach we took is very efficient, the module can do any
filtering of keys without building any list and cloning strings, it can
also read data from the key's value. but if the user tries to re-open
the key, or any other key, this can cause dict re-hashing (dictFind does
that), and that's very bad to do from inside dictScan.
this commit protects the dict from doing any rehashing during scan, but
also warns the user not to attempt any writes or command calls from
within the callback, for fear of unexpected side effects and crashes.
Diffstat (limited to 'src/dict.c')
-rw-r--r-- | src/dict.c | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/src/dict.c b/src/dict.c index 106467ef7..93e6c39a7 100644 --- a/src/dict.c +++ b/src/dict.c @@ -871,6 +871,10 @@ unsigned long dictScan(dict *d, if (dictSize(d) == 0) return 0; + /* Having a safe iterator means no rehashing can happen, see _dictRehashStep. + * This is needed in case the scan callback tries to do dictFind or alike. */ + d->iterators++; + if (!dictIsRehashing(d)) { t0 = &(d->ht[0]); m0 = t0->sizemask; @@ -937,6 +941,9 @@ unsigned long dictScan(dict *d, } while (v & (m0 ^ m1)); } + /* undo the ++ at the top */ + d->iterators--; + return v; } |