diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go index 8415a3a00..09802f976 100644 --- a/cmd/object-handlers.go +++ b/cmd/object-handlers.go @@ -242,7 +242,7 @@ func (api objectAPIHandlers) SelectObjectContentHandler(w http.ResponseWriter, r }, actualSize, ) - + defer objectRSC.Close() s3Select, err := s3select.NewS3Select(r.Body) if err != nil { if serr, ok := err.(s3select.SelectError); ok { @@ -3124,7 +3124,7 @@ func (api objectAPIHandlers) PostRestoreObjectHandler(w http.ResponseWriter, r * }, actualSize, ) - + defer objectRSC.Close() if err = rreq.SelectParameters.Open(objectRSC); err != nil { if serr, ok := err.(s3select.SelectError); ok { encodedErrorResponse := encodeResponse(APIErrorResponse{ diff --git a/internal/s3select/select.go b/internal/s3select/select.go index 900cc72c5..f2575e537 100644 --- a/internal/s3select/select.go +++ b/internal/s3select/select.go @@ -698,6 +698,11 @@ type ObjectReadSeekCloser struct { size int64 // actual object size regardless of compression/encryption offset int64 reader io.ReadCloser + + // reader can be closed idempotently multiple times + closerOnce sync.Once + // Error storing reader.Close() + closerErr error } // NewObjectReadSeekCloser creates a new ObjectReadSeekCloser. @@ -749,12 +754,11 @@ func (rsc *ObjectReadSeekCloser) Read(p []byte) (n int, err error) { // object for reading and a subsequent Close call is required to ensure // resources are freed. func (rsc *ObjectReadSeekCloser) Close() error { - if rsc.reader != nil { - err := rsc.reader.Close() - if err == nil { + rsc.closerOnce.Do(func() { + if rsc.reader != nil { + rsc.closerErr = rsc.reader.Close() rsc.reader = nil } - return err - } - return nil + }) + return rsc.closerErr }