From 19fb1086b212ab18e34e825b4bfdff6417ae2144 Mon Sep 17 00:00:00 2001 From: Klaus Post Date: Tue, 19 Jan 2021 17:51:46 -0800 Subject: [PATCH] select: Fix leak on compressed files (#11302) Properly close gzip reader when done reading fixes #11300 --- cmd/object-handlers.go | 2 +- pkg/s3select/progress.go | 26 ++++++++++++++++---------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go index 6b48b1841..087dbfe8d 100644 --- a/cmd/object-handlers.go +++ b/cmd/object-handlers.go @@ -243,6 +243,7 @@ func (api objectAPIHandlers) SelectObjectContentHandler(w http.ResponseWriter, r } return } + defer s3Select.Close() if err = s3Select.Open(getObject); err != nil { if serr, ok := err.(s3select.SelectError); ok { @@ -281,7 +282,6 @@ func (api objectAPIHandlers) SelectObjectContentHandler(w http.ResponseWriter, r } s3Select.Evaluate(w) - s3Select.Close() // Notify object accessed via a GET request. sendEvent(eventArgs{ diff --git a/pkg/s3select/progress.go b/pkg/s3select/progress.go index df68163fd..8edf873cd 100644 --- a/pkg/s3select/progress.go +++ b/pkg/s3select/progress.go @@ -57,6 +57,7 @@ type progressReader struct { processedReader *countUpReader closedMu sync.Mutex + gzr *gzip.Reader closed bool } @@ -72,15 +73,15 @@ func (pr *progressReader) Read(p []byte) (n int, err error) { } func (pr *progressReader) Close() error { - if pr.rc == nil { - return nil - } pr.closedMu.Lock() defer pr.closedMu.Unlock() if pr.closed { return nil } pr.closed = true + if pr.gzr != nil { + pr.gzr.Close() + } return pr.rc.Close() } @@ -92,30 +93,35 @@ func (pr *progressReader) Stats() (bytesScanned, bytesProcessed int64) { } func newProgressReader(rc io.ReadCloser, compType CompressionType) (*progressReader, error) { + if rc == nil { + return nil, errors.New("newProgressReader: nil reader provided") + } scannedReader := newCountUpReader(rc) - var r io.Reader + pr := progressReader{ + rc: rc, + scannedReader: scannedReader, + } var err error + var r io.Reader switch compType { case noneType: r = scannedReader case gzipType: - r, err = gzip.NewReader(scannedReader) + pr.gzr, err = gzip.NewReader(scannedReader) if err != nil { if errors.Is(err, gzip.ErrHeader) || errors.Is(err, gzip.ErrChecksum) { return nil, errInvalidGZIPCompressionFormat(err) } return nil, errTruncatedInput(err) } + r = pr.gzr case bzip2Type: r = bzip2.NewReader(scannedReader) default: return nil, errInvalidCompressionFormat(fmt.Errorf("unknown compression type '%v'", compType)) } + pr.processedReader = newCountUpReader(r) - return &progressReader{ - rc: rc, - scannedReader: scannedReader, - processedReader: newCountUpReader(r), - }, nil + return &pr, nil }