github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/pkg/channel/writer.go (about) 1 package channel 2 3 import ( 4 "fmt" 5 "io" 6 "sync" 7 8 "github.com/pkg/errors" 9 ) 10 11 // WriteCloser is an io.WriteCloser that that proxies Write() calls to a channel 12 // The []byte buffer of the Write() is queued on the channel as one message. 13 type WriteCloser interface { 14 io.WriteCloser 15 Chan() <-chan []byte 16 } 17 18 type writeCloser struct { 19 ch chan []byte 20 mux sync.Mutex 21 } 22 23 // NewWriter initializes a new channel writer 24 func NewWriter(c chan []byte) WriteCloser { 25 return &writeCloser{ 26 ch: c, 27 } 28 } 29 30 // Chan returns the R/O channel behind WriteCloser 31 func (w *writeCloser) Chan() <-chan []byte { 32 return w.ch 33 } 34 35 // Write method for WriteCloser 36 func (w *writeCloser) Write(b []byte) (bLen int, err error) { 37 // https://github.com/containers/podman/issues/7896 38 // when podman-remote pull image, if it was killed, the server will panic: send on closed channel 39 // so handle it 40 defer func() { 41 if rErr := recover(); rErr != nil { 42 err = fmt.Errorf("%s", rErr) 43 } 44 }() 45 if w == nil || w.ch == nil { 46 return 0, errors.New("use channel.NewWriter() to initialize a WriteCloser") 47 } 48 49 w.mux.Lock() 50 defer w.mux.Unlock() 51 buf := make([]byte, len(b)) 52 copy(buf, b) 53 w.ch <- buf 54 55 return len(b), nil 56 } 57 58 // Close method for WriteCloser 59 func (w *writeCloser) Close() error { 60 close(w.ch) 61 return nil 62 }