123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- package remote // import "github.com/docker/docker/libcontainerd/remote"
- import (
- "io"
- "net"
- "sync"
- winio "github.com/Microsoft/go-winio"
- "github.com/containerd/containerd/cio"
- "github.com/pkg/errors"
- "github.com/sirupsen/logrus"
- // "golang.org/x/net/context"
- )
- type delayedConnection struct {
- l net.Listener
- con net.Conn
- wg sync.WaitGroup
- once sync.Once
- }
- func (dc *delayedConnection) Write(p []byte) (int, error) {
- dc.wg.Wait()
- if dc.con != nil {
- return dc.con.Write(p)
- }
- return 0, errors.New("use of closed network connection")
- }
- func (dc *delayedConnection) Read(p []byte) (int, error) {
- dc.wg.Wait()
- if dc.con != nil {
- return dc.con.Read(p)
- }
- return 0, errors.New("use of closed network connection")
- }
- func (dc *delayedConnection) unblockConnectionWaiters() {
- defer dc.once.Do(func() {
- dc.wg.Done()
- })
- }
- func (dc *delayedConnection) Close() error {
- dc.l.Close()
- if dc.con != nil {
- return dc.con.Close()
- }
- dc.unblockConnectionWaiters()
- return nil
- }
- type stdioPipes struct {
- stdin io.WriteCloser
- stdout io.ReadCloser
- stderr io.ReadCloser
- }
- // newStdioPipes creates actual fifos for stdio.
- func (c *client) newStdioPipes(fifos *cio.FIFOSet) (_ *stdioPipes, err error) {
- p := &stdioPipes{}
- if fifos.Stdin != "" {
- c.logger.WithFields(logrus.Fields{"stdin": fifos.Stdin}).Debug("listen")
- l, err := winio.ListenPipe(fifos.Stdin, nil)
- if err != nil {
- return nil, errors.Wrapf(err, "failed to create stdin pipe %s", fifos.Stdin)
- }
- dc := &delayedConnection{
- l: l,
- }
- dc.wg.Add(1)
- defer func() {
- if err != nil {
- dc.Close()
- }
- }()
- p.stdin = dc
- go func() {
- c.logger.WithFields(logrus.Fields{"stdin": fifos.Stdin}).Debug("accept")
- conn, err := l.Accept()
- if err != nil {
- dc.Close()
- if err != winio.ErrPipeListenerClosed {
- c.logger.WithError(err).Errorf("failed to accept stdin connection on %s", fifos.Stdin)
- }
- return
- }
- c.logger.WithFields(logrus.Fields{"stdin": fifos.Stdin}).Debug("connected")
- dc.con = conn
- dc.unblockConnectionWaiters()
- }()
- }
- if fifos.Stdout != "" {
- c.logger.WithFields(logrus.Fields{"stdout": fifos.Stdout}).Debug("listen")
- l, err := winio.ListenPipe(fifos.Stdout, nil)
- if err != nil {
- return nil, errors.Wrapf(err, "failed to create stdout pipe %s", fifos.Stdout)
- }
- dc := &delayedConnection{
- l: l,
- }
- dc.wg.Add(1)
- defer func() {
- if err != nil {
- dc.Close()
- }
- }()
- p.stdout = dc
- go func() {
- c.logger.WithFields(logrus.Fields{"stdout": fifos.Stdout}).Debug("accept")
- conn, err := l.Accept()
- if err != nil {
- dc.Close()
- if err != winio.ErrPipeListenerClosed {
- c.logger.WithError(err).Errorf("failed to accept stdout connection on %s", fifos.Stdout)
- }
- return
- }
- c.logger.WithFields(logrus.Fields{"stdout": fifos.Stdout}).Debug("connected")
- dc.con = conn
- dc.unblockConnectionWaiters()
- }()
- }
- if fifos.Stderr != "" {
- c.logger.WithFields(logrus.Fields{"stderr": fifos.Stderr}).Debug("listen")
- l, err := winio.ListenPipe(fifos.Stderr, nil)
- if err != nil {
- return nil, errors.Wrapf(err, "failed to create stderr pipe %s", fifos.Stderr)
- }
- dc := &delayedConnection{
- l: l,
- }
- dc.wg.Add(1)
- defer func() {
- if err != nil {
- dc.Close()
- }
- }()
- p.stderr = dc
- go func() {
- c.logger.WithFields(logrus.Fields{"stderr": fifos.Stderr}).Debug("accept")
- conn, err := l.Accept()
- if err != nil {
- dc.Close()
- if err != winio.ErrPipeListenerClosed {
- c.logger.WithError(err).Errorf("failed to accept stderr connection on %s", fifos.Stderr)
- }
- return
- }
- c.logger.WithFields(logrus.Fields{"stderr": fifos.Stderr}).Debug("connected")
- dc.con = conn
- dc.unblockConnectionWaiters()
- }()
- }
- return p, nil
- }
|