From 7766c5c90b1ef8fe45a31bba1467823cfdcc06d6 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 11018c199..d1ae045e2 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()