fix: a possible closer leak in SelectObjectHandler (#16598)

This commit is contained in:
jiuker 2023-02-17 17:44:40 +08:00 committed by GitHub
parent 3a6cd4f73d
commit e470268c7c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 12 additions and 8 deletions

View File

@ -242,7 +242,7 @@ func (api objectAPIHandlers) SelectObjectContentHandler(w http.ResponseWriter, r
}, },
actualSize, actualSize,
) )
defer objectRSC.Close()
s3Select, err := s3select.NewS3Select(r.Body) s3Select, err := s3select.NewS3Select(r.Body)
if err != nil { if err != nil {
if serr, ok := err.(s3select.SelectError); ok { if serr, ok := err.(s3select.SelectError); ok {
@ -3124,7 +3124,7 @@ func (api objectAPIHandlers) PostRestoreObjectHandler(w http.ResponseWriter, r *
}, },
actualSize, actualSize,
) )
defer objectRSC.Close()
if err = rreq.SelectParameters.Open(objectRSC); err != nil { if err = rreq.SelectParameters.Open(objectRSC); err != nil {
if serr, ok := err.(s3select.SelectError); ok { if serr, ok := err.(s3select.SelectError); ok {
encodedErrorResponse := encodeResponse(APIErrorResponse{ encodedErrorResponse := encodeResponse(APIErrorResponse{

View File

@ -698,6 +698,11 @@ type ObjectReadSeekCloser struct {
size int64 // actual object size regardless of compression/encryption size int64 // actual object size regardless of compression/encryption
offset int64 offset int64
reader io.ReadCloser reader io.ReadCloser
// reader can be closed idempotently multiple times
closerOnce sync.Once
// Error storing reader.Close()
closerErr error
} }
// NewObjectReadSeekCloser creates a new ObjectReadSeekCloser. // 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 // object for reading and a subsequent Close call is required to ensure
// resources are freed. // resources are freed.
func (rsc *ObjectReadSeekCloser) Close() error { func (rsc *ObjectReadSeekCloser) Close() error {
if rsc.reader != nil { rsc.closerOnce.Do(func() {
err := rsc.reader.Close() if rsc.reader != nil {
if err == nil { rsc.closerErr = rsc.reader.Close()
rsc.reader = nil rsc.reader = nil
} }
return err })
} return rsc.closerErr
return nil
} }