From 0af467d18f9d12b137af3b709c0af579c29d8414 Mon Sep 17 00:00:00 2001 From: antirez Date: Wed, 1 Jan 2020 18:10:39 +0100 Subject: [PATCH] Fix active expire division by zero. Likely fix #6723. This is what happens AFAIK: we enter the main loop where we expire stuff until a given percentage of keys is still found to be logically expired. There are however other potential exit conditions. However the "sampled" variable is not always incremented inside the loop, because we may found no valid slot as we scan the hash table, but just NULLs ad dict entries. So when the do/while loop condition is triggered at the end, we do (expired*100/sampled), dividing by zero if we sampled 0 keys. --- src/expire.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/expire.c b/src/expire.c index b4ab9ab18..5aff72ee0 100644 --- a/src/expire.c +++ b/src/expire.c @@ -203,8 +203,10 @@ void activeExpireCycle(int type) { * distribute the time evenly across DBs. */ current_db++; - /* Continue to expire if at the end of the cycle more than 25% - * of the keys were expired. */ + /* Continue to expire if at the end of the cycle there are still + * a big percentage of keys to expire, compared to the number of keys + * we scanned. The percentage, stored in config_cycle_acceptable_stale + * is not fixed, but depends on the Redis configured "expire effort". */ do { unsigned long num, slots; long long now, ttl_sum; @@ -305,8 +307,9 @@ void activeExpireCycle(int type) { } /* We don't repeat the cycle for the current database if there are * an acceptable amount of stale keys (logically expired but yet - * not reclained). */ - } while ((expired*100/sampled) > config_cycle_acceptable_stale); + * not reclaimed). */ + } while (sampled == 0 || + (expired*100/sampled) > config_cycle_acceptable_stale); } elapsed = ustime()-start;