github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/worker/gclient/connection/stream_handler.go (about) 1 package connection 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 "sync" 8 9 "code.cloudfoundry.org/garden/transport" 10 "code.cloudfoundry.org/lager" 11 ) 12 13 type streamHandler struct { 14 log lager.Logger 15 wg *sync.WaitGroup 16 } 17 18 func newStreamHandler(log lager.Logger) *streamHandler { 19 return &streamHandler{ 20 log: log, 21 wg: new(sync.WaitGroup), 22 } 23 } 24 25 func (sh *streamHandler) streamIn(processWriter io.WriteCloser, stdin io.Reader) { 26 if stdin == nil { 27 return 28 } 29 30 go func(processInputStream io.WriteCloser, stdin io.Reader, log lager.Logger) { 31 if _, err := io.Copy(processInputStream, stdin); err == nil { 32 processInputStream.Close() 33 } else { 34 log.Error("streaming-stdin-payload", err) 35 } 36 }(processWriter, stdin, sh.log) 37 } 38 39 func (sh *streamHandler) streamOut(streamWriter io.Writer, streamReader io.Reader) { 40 sh.wg.Add(1) 41 go func() { 42 io.Copy(streamWriter, streamReader) 43 sh.wg.Done() 44 }() 45 } 46 47 type waitReturn struct { 48 exitCode int 49 err error 50 } 51 52 func (sh *streamHandler) wait(decoder *json.Decoder) <-chan waitReturn { 53 result := make(chan waitReturn) 54 go func() { 55 for { 56 payload := &transport.ProcessPayload{} 57 err := decoder.Decode(payload) 58 if err != nil { 59 sh.wg.Wait() 60 result <- waitReturn{ 61 0, 62 fmt.Errorf("connection: decode failed: %s", err), 63 } 64 break 65 } 66 67 if payload.Error != nil { 68 sh.wg.Wait() 69 result <- waitReturn{ 70 0, 71 fmt.Errorf("connection: process error: %s", *payload.Error), 72 } 73 break 74 } 75 76 if payload.ExitStatus != nil { 77 sh.wg.Wait() 78 result <- waitReturn{ 79 int(*payload.ExitStatus), 80 nil, 81 } 82 break 83 } 84 85 // discard other payloads 86 } 87 defer close(result) 88 }() 89 return result 90 }