prevent deadlock in List() for B2 when b2.connections=1
This is a fix for the following situation (gh-1188): List() grabs a semaphore token upon entry, starts a goroutine, and does not release the token until the routine exits (via a defer). The goroutine iterates over the results from ListCurrentObjects(), sending them one at a time to a channel, where they are ultimately processed by be.Load(). Since be.Load() also needs a token, this will result in deadlock if b2.connections=1. This fix changes List() so that the token is only held during the call to ListCurrentObjects().
This commit is contained in:
parent
53a554c89d
commit
3304b0fcf0
1 changed files with 2 additions and 3 deletions
|
@ -307,18 +307,17 @@ func (be *b2Backend) List(ctx context.Context, t restic.FileType) <-chan string
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
|
||||||
be.sem.GetToken()
|
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer close(ch)
|
defer close(ch)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
defer be.sem.ReleaseToken()
|
|
||||||
|
|
||||||
prefix := be.Dirname(restic.Handle{Type: t})
|
prefix := be.Dirname(restic.Handle{Type: t})
|
||||||
cur := &b2.Cursor{Prefix: prefix}
|
cur := &b2.Cursor{Prefix: prefix}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
be.sem.GetToken()
|
||||||
objs, c, err := be.bucket.ListCurrentObjects(ctx, be.listMaxItems, cur)
|
objs, c, err := be.bucket.ListCurrentObjects(ctx, be.listMaxItems, cur)
|
||||||
|
be.sem.ReleaseToken()
|
||||||
if err != nil && err != io.EOF {
|
if err != nil && err != io.EOF {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue