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.
This commit is contained in:
Nick Craig-Wood 2019-11-18 12:19:44 +00:00
parent 1e6278556c
commit d46f8d0ae5

View file

@ -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 // WithBuffer - If the file is above a certain size it adds an Async reader
func (acc *Account) WithBuffer() *Account { func (acc *Account) WithBuffer() *Account {
// if already have a buffer then just return
if acc.withBuf {
return acc
}
acc.withBuf = true acc.withBuf = true
var buffers int var buffers int
if acc.size >= int64(fs.Config.BufferSize) || acc.size == -1 { 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 // async buffer (if any) and re-adding it
func (acc *Account) UpdateReader(in io.ReadCloser) { func (acc *Account) UpdateReader(in io.ReadCloser) {
acc.mu.Lock() acc.mu.Lock()
if acc.withBuf { withBuf := acc.withBuf
if withBuf {
acc.StopBuffering() acc.StopBuffering()
acc.withBuf = false
} }
acc.in = in acc.in = in
acc.close = in acc.close = in
acc.origIn = in acc.origIn = in
acc.closed = false acc.closed = false
if acc.withBuf { if withBuf {
acc.WithBuffer() acc.WithBuffer()
} }
acc.mu.Unlock() acc.mu.Unlock()