From f77027e6b7f7bef853f6b89d7e1f126e9c131195 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Thu, 12 Sep 2019 11:12:19 +0100 Subject: [PATCH] fs/accounting: Fix "file already closed" on transfer retries This was caused by the recent reworking of the accounting interface. The Transfer object was recycling the Accounting object without resetting the stream. See: https://forum.rclone.org/t/error-file-already-closed/11469/ See: https://forum.rclone.org/t/rclone-b2-sync-post-error-method-not-supported/11718/ --- fs/accounting/accounting.go | 8 ++++++-- fs/accounting/transfer.go | 2 ++ fs/operations/operations.go | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/fs/accounting/accounting.go b/fs/accounting/accounting.go index 81a1b56f5..b2544df72 100644 --- a/fs/accounting/accounting.go +++ b/fs/accounting/accounting.go @@ -118,11 +118,15 @@ func (acc *Account) StopBuffering() { // async buffer (if any) and re-adding it func (acc *Account) UpdateReader(in io.ReadCloser) { acc.mu.Lock() - acc.StopBuffering() + if acc.withBuf { + acc.StopBuffering() + } acc.in = in acc.close = in acc.origIn = in - acc.WithBuffer() + if acc.withBuf { + acc.WithBuffer() + } acc.mu.Unlock() } diff --git a/fs/accounting/transfer.go b/fs/accounting/transfer.go index 0d968661b..a1ab8d023 100644 --- a/fs/accounting/transfer.go +++ b/fs/accounting/transfer.go @@ -117,6 +117,8 @@ func (tr *Transfer) Account(in io.ReadCloser) *Account { tr.mu.Lock() if tr.acc == nil { tr.acc = newAccountSizeName(tr.stats, in, tr.size, tr.remote) + } else { + tr.acc.UpdateReader(in) } tr.mu.Unlock() return tr.acc diff --git a/fs/operations/operations.go b/fs/operations/operations.go index 14d01519a..524bca9c9 100644 --- a/fs/operations/operations.go +++ b/fs/operations/operations.go @@ -341,6 +341,7 @@ func Copy(ctx context.Context, f fs.Fs, dst fs.Object, remote string, src fs.Obj } else { actionTaken = "Copied (Rcat, new)" } + // NB Rcat closes in0 dst, err = Rcat(ctx, f, remote, in0, src.ModTime(ctx)) newDst = dst } else {