github.com/haraldrudell/parl@v0.4.176/pio/copy-thread.go (about) 1 /* 2 © 2023–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/) 3 ISC License 4 */ 5 6 package pio 7 8 import ( 9 "context" 10 "errors" 11 "io" 12 "io/fs" 13 14 "github.com/haraldrudell/parl" 15 "github.com/haraldrudell/parl/perrors" 16 "github.com/haraldrudell/parl/pruntime" 17 ) 18 19 var cx pruntime.CachedLocation 20 21 // CopyThread copies from an io.Reader to an io.Writer. 22 // - label is used for thread identification on panics 23 // - errCh receives result and makes thread awaitable 24 // - if ctx, a CancelContext, is non-nil and error occurs, ctx is cancelled 25 // - CopyThread itself never fails 26 func CopyThread( 27 label string, reader io.Reader, writer io.Writer, 28 errCh chan<- error, ctx context.Context, 29 ) { 30 var err error 31 defer func() { errCh <- err }() 32 if ctx != nil { 33 defer parl.CancelOnError(&err, ctx) // cancel the command if copyThread fails 34 } 35 defer parl.RecoverAnnotation("copy command i/o "+label, &err, parl.NoOnError) 36 37 if _, err = io.Copy(writer, reader); perrors.Is(&err, "%s %s %w", label, cx.PackFunc(), err) { 38 39 // if the process terminates quickly, exec.Command might have already closed 40 // stdout stderr before the copyThread is scheduled to start 41 if errors.Is(err, fs.ErrClosed) { 42 err = nil // ignore quickly closed errors 43 } 44 45 return 46 } 47 }