Skip to content

Commit 464aa04

Browse files
authored
fix infinite sleep in performEvictions when have lazyfree jobs (redis#11237)
This bug is introduced in redis#7653. (Redis 6.2.0) When `server.maxmemory_eviction_tenacity` is 100, `eviction_time_limit_us` is `ULONG_MAX`, and if we cannot find the best key to delete (e.g. maxmemory-policy is `volatile-lru` and all keys with ttl have been evicted), in `cant_free` redis will sleep forever if some items are being freed in the lazyfree thread.
1 parent d144dc9 commit 464aa04

File tree

1 file changed

+9
-3
lines changed

1 file changed

+9
-3
lines changed

src/evict.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ int performEvictions(void) {
595595
{
596596
struct evictionPoolEntry *pool = EvictionPoolLRU;
597597

598-
while(bestkey == NULL) {
598+
while (bestkey == NULL) {
599599
unsigned long total_keys = 0, keys;
600600

601601
/* We don't want to make local-db choices when expiring keys,
@@ -738,12 +738,18 @@ int performEvictions(void) {
738738
/* At this point, we have run out of evictable items. It's possible
739739
* that some items are being freed in the lazyfree thread. Perform a
740740
* short wait here if such jobs exist, but don't wait long. */
741-
if (bioPendingJobsOfType(BIO_LAZY_FREE)) {
742-
usleep(eviction_time_limit_us);
741+
mstime_t lazyfree_latency;
742+
latencyStartMonitor(lazyfree_latency);
743+
while (bioPendingJobsOfType(BIO_LAZY_FREE) &&
744+
elapsedUs(evictionTimer) < eviction_time_limit_us) {
743745
if (getMaxmemoryState(NULL,NULL,NULL,NULL) == C_OK) {
744746
result = EVICT_OK;
747+
break;
745748
}
749+
usleep(eviction_time_limit_us < 1000 ? eviction_time_limit_us : 1000);
746750
}
751+
latencyEndMonitor(lazyfree_latency);
752+
latencyAddSampleIfNeeded("eviction-lazyfree",lazyfree_latency);
747753
}
748754

749755
serverAssert(server.core_propagates); /* This function should not be re-entrant */

0 commit comments

Comments
 (0)