bloblru: fix race condition that can compute value multiple times

This commit is contained in:
Michael Eischer 2024-05-26 12:37:24 +02:00
parent 3828313974
commit 0ad0b7ca7c

View file

@ -114,10 +114,19 @@ func (c *Cache) GetOrCompute(id restic.ID, compute func() ([]byte, error)) ([]by
if isDownloading { if isDownloading {
// wait for result of parallel download // wait for result of parallel download
<-waitForResult <-waitForResult
blob, ok := c.Get(id) }
if ok {
return blob, nil // try again. This is necessary independent of whether isDownloading is true or not.
} // The calls to `c.Get()` and checking/adding the entry in `c.inProgress` are not atomic,
// thus the item might have been computed in the meantime.
// The following scenario would compute() the value multiple times otherwise:
// Goroutine A does not find a value in the initial call to `c.Get`, then goroutine B
// takes over, caches the computed value and cleans up its channel in c.inProgress.
// Then goroutine A continues, does not detect a parallel computation and would try
// to call compute() again.
blob, ok = c.Get(id)
if ok {
return blob, nil
} }
// download it // download it