github.com/getong/docker@v1.13.1/distribution/utils/progress.go (about) 1 package utils 2 3 import ( 4 "io" 5 "net" 6 "os" 7 "syscall" 8 9 "github.com/Sirupsen/logrus" 10 "github.com/docker/docker/pkg/progress" 11 "github.com/docker/docker/pkg/streamformatter" 12 ) 13 14 // WriteDistributionProgress is a helper for writing progress from chan to JSON 15 // stream with an optional cancel function. 16 func WriteDistributionProgress(cancelFunc func(), outStream io.Writer, progressChan <-chan progress.Progress) { 17 progressOutput := streamformatter.NewJSONStreamFormatter().NewProgressOutput(outStream, false) 18 operationCancelled := false 19 20 for prog := range progressChan { 21 if err := progressOutput.WriteProgress(prog); err != nil && !operationCancelled { 22 // don't log broken pipe errors as this is the normal case when a client aborts 23 if isBrokenPipe(err) { 24 logrus.Info("Pull session cancelled") 25 } else { 26 logrus.Errorf("error writing progress to client: %v", err) 27 } 28 cancelFunc() 29 operationCancelled = true 30 // Don't return, because we need to continue draining 31 // progressChan until it's closed to avoid a deadlock. 32 } 33 } 34 } 35 36 func isBrokenPipe(e error) bool { 37 if netErr, ok := e.(*net.OpError); ok { 38 e = netErr.Err 39 if sysErr, ok := netErr.Err.(*os.SyscallError); ok { 40 e = sysErr.Err 41 } 42 } 43 return e == syscall.EPIPE 44 }