118 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			118 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package containerd
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"io"
 | |
| 	"net"
 | |
| 	"sync"
 | |
| 
 | |
| 	winio "github.com/Microsoft/go-winio"
 | |
| 	"github.com/containerd/containerd/log"
 | |
| 	"github.com/pkg/errors"
 | |
| )
 | |
| 
 | |
| const pipeRoot = `\\.\pipe`
 | |
| 
 | |
| // NewFifos returns a new set of fifos for the task
 | |
| func NewFifos(id string) (*FIFOSet, error) {
 | |
| 	return &FIFOSet{
 | |
| 		In:  fmt.Sprintf(`%s\ctr-%s-stdin`, pipeRoot, id),
 | |
| 		Out: fmt.Sprintf(`%s\ctr-%s-stdout`, pipeRoot, id),
 | |
| 		Err: fmt.Sprintf(`%s\ctr-%s-stderr`, pipeRoot, id),
 | |
| 	}, nil
 | |
| }
 | |
| 
 | |
| func copyIO(fifos *FIFOSet, ioset *ioSet, tty bool) (_ *wgCloser, err error) {
 | |
| 	var (
 | |
| 		wg  sync.WaitGroup
 | |
| 		set []io.Closer
 | |
| 	)
 | |
| 
 | |
| 	if fifos.In != "" {
 | |
| 		l, err := winio.ListenPipe(fifos.In, nil)
 | |
| 		if err != nil {
 | |
| 			return nil, errors.Wrapf(err, "failed to create stdin pipe %s", fifos.In)
 | |
| 		}
 | |
| 		defer func(l net.Listener) {
 | |
| 			if err != nil {
 | |
| 				l.Close()
 | |
| 			}
 | |
| 		}(l)
 | |
| 		set = append(set, l)
 | |
| 
 | |
| 		go func() {
 | |
| 			c, err := l.Accept()
 | |
| 			if err != nil {
 | |
| 				log.L.WithError(err).Errorf("failed to accept stdin connection on %s", fifos.In)
 | |
| 				return
 | |
| 			}
 | |
| 			io.Copy(c, ioset.in)
 | |
| 			c.Close()
 | |
| 			l.Close()
 | |
| 		}()
 | |
| 	}
 | |
| 
 | |
| 	if fifos.Out != "" {
 | |
| 		l, err := winio.ListenPipe(fifos.Out, nil)
 | |
| 		if err != nil {
 | |
| 			return nil, errors.Wrapf(err, "failed to create stdin pipe %s", fifos.Out)
 | |
| 		}
 | |
| 		defer func(l net.Listener) {
 | |
| 			if err != nil {
 | |
| 				l.Close()
 | |
| 			}
 | |
| 		}(l)
 | |
| 		set = append(set, l)
 | |
| 
 | |
| 		wg.Add(1)
 | |
| 		go func() {
 | |
| 			defer wg.Done()
 | |
| 			c, err := l.Accept()
 | |
| 			if err != nil {
 | |
| 				log.L.WithError(err).Errorf("failed to accept stdout connection on %s", fifos.Out)
 | |
| 				return
 | |
| 			}
 | |
| 			io.Copy(ioset.out, c)
 | |
| 			c.Close()
 | |
| 			l.Close()
 | |
| 		}()
 | |
| 	}
 | |
| 
 | |
| 	if !tty && fifos.Err != "" {
 | |
| 		l, err := winio.ListenPipe(fifos.Err, nil)
 | |
| 		if err != nil {
 | |
| 			return nil, errors.Wrapf(err, "failed to create stderr pipe %s", fifos.Err)
 | |
| 		}
 | |
| 		defer func(l net.Listener) {
 | |
| 			if err != nil {
 | |
| 				l.Close()
 | |
| 			}
 | |
| 		}(l)
 | |
| 		set = append(set, l)
 | |
| 
 | |
| 		wg.Add(1)
 | |
| 		go func() {
 | |
| 			defer wg.Done()
 | |
| 			c, err := l.Accept()
 | |
| 			if err != nil {
 | |
| 				log.L.WithError(err).Errorf("failed to accept stderr connection on %s", fifos.Err)
 | |
| 				return
 | |
| 			}
 | |
| 			io.Copy(ioset.err, c)
 | |
| 			c.Close()
 | |
| 			l.Close()
 | |
| 		}()
 | |
| 	}
 | |
| 
 | |
| 	return &wgCloser{
 | |
| 		wg:  &wg,
 | |
| 		dir: fifos.Dir,
 | |
| 		set: set,
 | |
| 		cancel: func() {
 | |
| 			for _, l := range set {
 | |
| 				l.Close()
 | |
| 			}
 | |
| 		},
 | |
| 	}, nil
 | |
| }
 | 
