github.com/haraldrudell/parl@v0.4.176/pexec/copy-thread.go (about)

     1  /*
     2  © 2021–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
     3  ISC License
     4  */
     5  
     6  package pexec
     7  
     8  import (
     9  	"context"
    10  	"errors"
    11  	"io"
    12  	"io/fs"
    13  	"sync"
    14  
    15  	"github.com/haraldrudell/parl"
    16  	"github.com/haraldrudell/parl/perrors"
    17  )
    18  
    19  // copyThread copies from a io.Reader to io.Writer.
    20  //   - label is used for thread identification on panics
    21  //   - reader could be the stdin io.Reader being copied to the execCmd.StdinPipe Writer
    22  //   - addError receives panics
    23  //   - on panic exeCtx context is cancelled
    24  //   - the thread itself never fails
    25  func copyThread(label string,
    26  	reader io.Reader, writer io.Writer,
    27  	addError func(err error), execCtx context.Context,
    28  	wg *sync.WaitGroup) {
    29  	defer wg.Done()
    30  	var err error
    31  	defer parl.CancelOnError(&err, execCtx) // cancel the command if copyThread failes
    32  	defer parl.RecoverAnnotation("copy command i/o "+label, &err, addError)
    33  
    34  	if _, err = io.Copy(writer, reader); perrors.Is(&err, "%s io.Copy %w", label, err) {
    35  
    36  		// if the process terminates quickly, exec.Command might have already closed
    37  		// stdout stderr before the copyThread is scheduled to start
    38  		if errors.Is(err, fs.ErrClosed) {
    39  			err = nil // ignore quickly closed errors
    40  		}
    41  
    42  		return
    43  	}
    44  }