mirror of
https://github.com/rclone/rclone.git
synced 2024-12-23 07:29:35 +01:00
vfs: fix hang in read wait code - Fixes #4039
Before this fix, rclone would sometimes hang in vfs.readAt(). This was due to a race condition causing rclone to miss the timeout signal. This was fixed by a small amount of extra locking. This very likely also fixes a number of "failed to wait for in-sequence read" errors.
This commit is contained in:
parent
57ee25d75a
commit
3de9bd9d04
13
vfs/read.go
13
vfs/read.go
@ -5,7 +5,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -238,18 +237,22 @@ func (fh *ReadFileHandle) readAt(p []byte, off int64) (n int, err error) {
|
|||||||
maxWait := fh.file.VFS().Opt.ReadWait
|
maxWait := fh.file.VFS().Opt.ReadWait
|
||||||
timeout := time.NewTimer(maxWait)
|
timeout := time.NewTimer(maxWait)
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
abort := int32(0)
|
abort := false
|
||||||
go func() {
|
go func() {
|
||||||
select {
|
select {
|
||||||
case <-timeout.C:
|
case <-timeout.C:
|
||||||
// set abort flag an give all the waiting goroutines a kick on timeout
|
// take the lock to make sure that fh.cond.Wait() is called before
|
||||||
atomic.StoreInt32(&abort, 1)
|
// fh.cond.Broadcast. NB fh.cond.L == fh.mu
|
||||||
|
fh.mu.Lock()
|
||||||
|
// set abort flag and give all the waiting goroutines a kick on timeout
|
||||||
|
abort = true
|
||||||
fs.Debugf(fh.remote, "aborting in-sequence read wait, off=%d", off)
|
fs.Debugf(fh.remote, "aborting in-sequence read wait, off=%d", off)
|
||||||
fh.cond.Broadcast()
|
fh.cond.Broadcast()
|
||||||
|
fh.mu.Unlock()
|
||||||
case <-done:
|
case <-done:
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
for fh.offset != off && atomic.LoadInt32(&abort) == 0 {
|
for fh.offset != off && !abort {
|
||||||
fs.Debugf(fh.remote, "waiting for in-sequence read to %d for %v", off, maxWait)
|
fs.Debugf(fh.remote, "waiting for in-sequence read to %d for %v", off, maxWait)
|
||||||
fh.cond.Wait()
|
fh.cond.Wait()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user