Skip to content

Commit

Permalink
cache: fix race when clearning a cache (#261)
Browse files Browse the repository at this point in the history
When clearing a cache while other goroutines are actively Wait()-ing for it, the waiting goroutines can become blocked indefinitely if one of the cache items is flushed by the Clear() code instead of by the background worker, because the Clear() code is not marking sync.WaitGroups as done.
  • Loading branch information
vmg authored Mar 18, 2021
1 parent 6b99600 commit 74754f6
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 0 deletions.
4 changes: 4 additions & 0 deletions cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,10 @@ loop:
for {
select {
case i := <-c.setBuf:
if i.wg != nil {
i.wg.Done()
continue
}
if i.flag != itemUpdate {
// In itemUpdate, the value is already set in the store. So, no need to call
// onEvict here.
Expand Down
31 changes: 31 additions & 0 deletions cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,37 @@ func init() {
bucketDurationSecs = 1
}

func TestBlockOnClear(t *testing.T) {
c, err := NewCache(&Config{
NumCounters: 100,
MaxCost: 10,
BufferItems: 64,
Metrics: false,
})
require.NoError(t, err)
defer c.Close()

done := make(chan struct{})

go func() {
for i := 0; i < 10; i++ {
c.Wait()
}
close(done)
}()

for i := 0; i < 10; i++ {
c.Clear()
}

select {
case <-done:
// We're OK
case <-time.After(1 * time.Second):
t.Fatalf("timed out while waiting on cache")
}
}

// Regression test for bug https://github.com/dgraph-io/ristretto/issues/167
func TestDropUpdates(t *testing.T) {
originalSetBugSize := setBufSize
Expand Down

0 comments on commit 74754f6

Please sign in to comment.