mirror of
https://github.com/octoleo/restic.git
synced 2024-12-23 11:28:54 +00:00
Merge pull request #3014 from ivandeex/pr-stream-reset
Fix sporadic stream reset between rclone and restic
This commit is contained in:
commit
a5592e83f7
@ -173,7 +173,32 @@ func (b *Backend) IsNotExist(err error) bool {
|
||||
// Load runs fn with a reader that yields the contents of the file at h at the
|
||||
// given offset.
|
||||
func (b *Backend) Load(ctx context.Context, h restic.Handle, length int, offset int64, fn func(rd io.Reader) error) error {
|
||||
return backend.DefaultLoad(ctx, h, length, offset, b.openReader, fn)
|
||||
r, err := b.openReader(ctx, h, length, offset)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = fn(r)
|
||||
if err != nil {
|
||||
_ = r.Close() // ignore error here
|
||||
return err
|
||||
}
|
||||
|
||||
// Note: readerat.ReadAt() (the fn) uses io.ReadFull() that doesn't
|
||||
// wait for EOF after reading body. Due to HTTP/2 stream multiplexing
|
||||
// and goroutine timings the EOF frame arrives from server (eg. rclone)
|
||||
// with a delay after reading body. Immediate close might trigger
|
||||
// HTTP/2 stream reset resulting in the *stream closed* error on server,
|
||||
// so we wait for EOF before closing body.
|
||||
var buf [1]byte
|
||||
_, err = r.Read(buf[:])
|
||||
if err == io.EOF {
|
||||
err = nil
|
||||
}
|
||||
|
||||
if e := r.Close(); err == nil {
|
||||
err = e
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (b *Backend) openReader(ctx context.Context, h restic.Handle, length int, offset int64) (io.ReadCloser, error) {
|
||||
|
Loading…
Reference in New Issue
Block a user