Kaynağa Gözat

Merge pull request #47222 from vvoland/pkg-pools-close-noop-25

[25.0 backport] pkg/ioutils: Make subsequent Close attempts noop
Sebastiaan van Stijn 1 yıl önce
ebeveyn
işleme
5babfee371
2 değiştirilmiş dosya ile 30 ekleme ve 1 silme
  1. 21 0
      pkg/ioutils/readers.go
  2. 9 1
      pkg/ioutils/writers.go

+ 21 - 0
pkg/ioutils/readers.go

@@ -3,11 +3,15 @@ package ioutils // import "github.com/docker/docker/pkg/ioutils"
 import (
 	"context"
 	"io"
+	"runtime/debug"
+	"sync/atomic"
 
 	// make sure crypto.SHA256, crypto.sha512 and crypto.SHA384 are registered
 	// TODO remove once https://github.com/opencontainers/go-digest/pull/64 is merged.
 	_ "crypto/sha256"
 	_ "crypto/sha512"
+
+	"github.com/containerd/log"
 )
 
 // ReadCloserWrapper wraps an io.Reader, and implements an io.ReadCloser
@@ -16,10 +20,15 @@ import (
 type ReadCloserWrapper struct {
 	io.Reader
 	closer func() error
+	closed atomic.Bool
 }
 
 // Close calls back the passed closer function
 func (r *ReadCloserWrapper) Close() error {
+	if !r.closed.CompareAndSwap(false, true) {
+		subsequentCloseWarn("ReadCloserWrapper")
+		return nil
+	}
 	return r.closer()
 }
 
@@ -87,6 +96,7 @@ type cancelReadCloser struct {
 	cancel func()
 	pR     *io.PipeReader // Stream to read from
 	pW     *io.PipeWriter
+	closed atomic.Bool
 }
 
 // NewCancelReadCloser creates a wrapper that closes the ReadCloser when the
@@ -146,6 +156,17 @@ func (p *cancelReadCloser) closeWithError(err error) {
 // Close closes the wrapper its underlying reader. It will cause
 // future calls to Read to return io.EOF.
 func (p *cancelReadCloser) Close() error {
+	if !p.closed.CompareAndSwap(false, true) {
+		subsequentCloseWarn("cancelReadCloser")
+		return nil
+	}
 	p.closeWithError(io.EOF)
 	return nil
 }
+
+func subsequentCloseWarn(name string) {
+	log.G(context.TODO()).Error("subsequent attempt to close " + name)
+	if log.GetLevel() >= log.DebugLevel {
+		log.G(context.TODO()).Errorf("stack trace: %s", string(debug.Stack()))
+	}
+}

+ 9 - 1
pkg/ioutils/writers.go

@@ -1,6 +1,9 @@
 package ioutils // import "github.com/docker/docker/pkg/ioutils"
 
-import "io"
+import (
+	"io"
+	"sync/atomic"
+)
 
 // NopWriter represents a type which write operation is nop.
 type NopWriter struct{}
@@ -29,9 +32,14 @@ func (f *NopFlusher) Flush() {}
 type writeCloserWrapper struct {
 	io.Writer
 	closer func() error
+	closed atomic.Bool
 }
 
 func (r *writeCloserWrapper) Close() error {
+	if !r.closed.CompareAndSwap(false, true) {
+		subsequentCloseWarn("WriteCloserWrapper")
+		return nil
+	}
 	return r.closer()
 }