Fix race in Lister.Finished which was causing the tests to be unreliable
This commit is contained in:
parent
e2bf9eb8e9
commit
b6848a3edb
1 changed files with 22 additions and 16 deletions
20
fs/lister.go
20
fs/lister.go
|
@ -11,13 +11,13 @@ type listerResult struct {
|
||||||
Err error
|
Err error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lister objects are used for conniltrolling listing of Fs objects
|
// Lister objects are used for controlling listing of Fs objects
|
||||||
type Lister struct {
|
type Lister struct {
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
buffer int
|
buffer int
|
||||||
abort bool
|
abort bool
|
||||||
results chan listerResult
|
results chan listerResult
|
||||||
finished sync.Once
|
closeOnce sync.Once
|
||||||
level int
|
level int
|
||||||
filter *Filter
|
filter *Filter
|
||||||
err error
|
err error
|
||||||
|
@ -172,6 +172,15 @@ func (o *Lister) IncludeDirectory(remote string) bool {
|
||||||
return o.filter.IncludeDirectory(remote)
|
return o.filter.IncludeDirectory(remote)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// finished closes the results channel and sets abort - must be called
|
||||||
|
// with o.mu held.
|
||||||
|
func (o *Lister) finished() {
|
||||||
|
o.closeOnce.Do(func() {
|
||||||
|
close(o.results)
|
||||||
|
o.abort = true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// SetError will set an error state, and will cause the listing to
|
// SetError will set an error state, and will cause the listing to
|
||||||
// be aborted.
|
// be aborted.
|
||||||
// Multiple goroutines can set the error state concurrently,
|
// Multiple goroutines can set the error state concurrently,
|
||||||
|
@ -181,19 +190,16 @@ func (o *Lister) SetError(err error) {
|
||||||
if err != nil && !o.abort {
|
if err != nil && !o.abort {
|
||||||
o.err = err
|
o.err = err
|
||||||
o.results <- listerResult{Err: err}
|
o.results <- listerResult{Err: err}
|
||||||
|
o.finished()
|
||||||
}
|
}
|
||||||
o.mu.Unlock()
|
o.mu.Unlock()
|
||||||
o.Finished()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finished should be called when listing is finished
|
// Finished should be called when listing is finished
|
||||||
func (o *Lister) Finished() {
|
func (o *Lister) Finished() {
|
||||||
o.finished.Do(func() {
|
|
||||||
o.mu.Lock()
|
o.mu.Lock()
|
||||||
o.abort = true
|
o.finished()
|
||||||
close(o.results)
|
|
||||||
o.mu.Unlock()
|
o.mu.Unlock()
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsFinished returns whether the directory listing is finished or not
|
// IsFinished returns whether the directory listing is finished or not
|
||||||
|
|
Loading…
Reference in a new issue