singleflight: fix duplicate deleting key when Forget called
When Forget was called, we delete key associated with current call from map. When that call is done, it does delete key again, causing the same key set by other call after Forget lost. To fix it, adding a boolean value to check whether the call is forgotten, the call only does delete key if Forget is not called. Fixes golang/go#31420 Change-Id: I9708352ca3ff76c77f659916b37a496fdeb480d2 Reviewed-on: https://go-review.googlesource.com/c/sync/+/171897 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
e225da77a7
commit
56d357773e
2 changed files with 82 additions and 1 deletions
|
|
@ -17,6 +17,10 @@ type call struct {
|
|||
val interface{}
|
||||
err error
|
||||
|
||||
// forgotten indicates whether Forget was called with this call's key
|
||||
// while the call was still in flight.
|
||||
forgotten bool
|
||||
|
||||
// These fields are read and written with the singleflight
|
||||
// mutex held before the WaitGroup is done, and are read but
|
||||
// not written after the WaitGroup is done.
|
||||
|
|
@ -94,7 +98,9 @@ func (g *Group) doCall(c *call, key string, fn func() (interface{}, error)) {
|
|||
c.wg.Done()
|
||||
|
||||
g.mu.Lock()
|
||||
delete(g.m, key)
|
||||
if !c.forgotten {
|
||||
delete(g.m, key)
|
||||
}
|
||||
for _, ch := range c.chans {
|
||||
ch <- Result{c.val, c.err, c.dups > 0}
|
||||
}
|
||||
|
|
@ -106,6 +112,9 @@ func (g *Group) doCall(c *call, key string, fn func() (interface{}, error)) {
|
|||
// an earlier call to complete.
|
||||
func (g *Group) Forget(key string) {
|
||||
g.mu.Lock()
|
||||
if c, ok := g.m[key]; ok {
|
||||
c.forgotten = true
|
||||
}
|
||||
delete(g.m, key)
|
||||
g.mu.Unlock()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue