Skip to content

Commit 80a665e

Browse files
committed
Fix race condition: failed records must be discarded
1 parent b79f5ac commit 80a665e

File tree

2 files changed

+8
-2
lines changed

2 files changed

+8
-2
lines changed

cache.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ loadOrStore:
122122
defer func() {
123123
if r := recover(); r != nil {
124124
c.backend.Delete(key)
125-
c.backend.Release(newElem)
125+
c.backend.Discard(newElem)
126126

127127
panic(r)
128128
}
@@ -131,7 +131,7 @@ loadOrStore:
131131
value, ttl, err := f()
132132
if err != nil {
133133
c.backend.Delete(key)
134-
c.backend.Release(newElem)
134+
c.backend.Discard(newElem)
135135

136136
var zero V
137137
return zero, err

internal/backend/backend.go

+6
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ func (r *record[V]) Value() V {
2222
return r.value
2323
}
2424

25+
// Wait for the record to be either released or discarded.
2526
func (r *record[V]) Wait() {
2627
r.wg.Wait()
2728
}
@@ -94,6 +95,11 @@ func (b *Backend[K, V]) Release(elem Element[V]) {
9495
b.pool.Put(elem)
9596
}
9697

98+
// Discard a reserved uninitialized element.
99+
func (*Backend[K, V]) Discard(elem Element[V]) {
100+
elem.Value.wg.Done()
101+
}
102+
97103
// Initialize a previously stored uninitialized element.
98104
func (b *Backend[K, V]) Initialize(key K, value V, ttl time.Duration) {
99105
b.mu.Lock()

0 commit comments

Comments
 (0)