From d46f8d0ae5405e9208b9925db8ae4b93519470e8 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Mon, 18 Nov 2019 12:19:44 +0000 Subject: [PATCH] accounting: fix memory leak on retries operations Before this change if an operation was retried on operations.Copy and the operation was large enough to use an async buffer then an async buffer was leaked on the retry. This leaked memory, a file handle and a go routine. After this change if Account.WithBuffer is called and there is already a buffer, then a new one won't be allocated. --- fs/accounting/accounting.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/fs/accounting/accounting.go b/fs/accounting/accounting.go index 1c838a55b..dd9a5145f 100644 --- a/fs/accounting/accounting.go +++ b/fs/accounting/accounting.go @@ -70,6 +70,10 @@ func newAccountSizeName(stats *StatsInfo, in io.ReadCloser, size int64, name str // WithBuffer - If the file is above a certain size it adds an Async reader func (acc *Account) WithBuffer() *Account { + // if already have a buffer then just return + if acc.withBuf { + return acc + } acc.withBuf = true var buffers int if acc.size >= int64(fs.Config.BufferSize) || acc.size == -1 { @@ -118,14 +122,16 @@ func (acc *Account) StopBuffering() { // async buffer (if any) and re-adding it func (acc *Account) UpdateReader(in io.ReadCloser) { acc.mu.Lock() - if acc.withBuf { + withBuf := acc.withBuf + if withBuf { acc.StopBuffering() + acc.withBuf = false } acc.in = in acc.close = in acc.origIn = in acc.closed = false - if acc.withBuf { + if withBuf { acc.WithBuffer() } acc.mu.Unlock()