github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/libcontainerd/remote/client_io_windows.go (about) 1 package remote // import "github.com/demonoid81/moby/libcontainerd/remote" 2 3 import ( 4 "io" 5 "net" 6 "sync" 7 8 winio "github.com/Microsoft/go-winio" 9 "github.com/containerd/containerd/cio" 10 "github.com/pkg/errors" 11 "github.com/sirupsen/logrus" 12 // "golang.org/x/net/context" 13 ) 14 15 type delayedConnection struct { 16 l net.Listener 17 con net.Conn 18 wg sync.WaitGroup 19 once sync.Once 20 } 21 22 func (dc *delayedConnection) Write(p []byte) (int, error) { 23 dc.wg.Wait() 24 if dc.con != nil { 25 return dc.con.Write(p) 26 } 27 return 0, errors.New("use of closed network connection") 28 } 29 30 func (dc *delayedConnection) Read(p []byte) (int, error) { 31 dc.wg.Wait() 32 if dc.con != nil { 33 return dc.con.Read(p) 34 } 35 return 0, errors.New("use of closed network connection") 36 } 37 38 func (dc *delayedConnection) unblockConnectionWaiters() { 39 defer dc.once.Do(func() { 40 dc.wg.Done() 41 }) 42 } 43 44 func (dc *delayedConnection) Close() error { 45 dc.l.Close() 46 if dc.con != nil { 47 return dc.con.Close() 48 } 49 dc.unblockConnectionWaiters() 50 return nil 51 } 52 53 type stdioPipes struct { 54 stdin io.WriteCloser 55 stdout io.ReadCloser 56 stderr io.ReadCloser 57 } 58 59 // newStdioPipes creates actual fifos for stdio. 60 func (c *client) newStdioPipes(fifos *cio.FIFOSet) (_ *stdioPipes, err error) { 61 p := &stdioPipes{} 62 if fifos.Stdin != "" { 63 c.logger.WithFields(logrus.Fields{"stdin": fifos.Stdin}).Debug("listen") 64 l, err := winio.ListenPipe(fifos.Stdin, nil) 65 if err != nil { 66 return nil, errors.Wrapf(err, "failed to create stdin pipe %s", fifos.Stdin) 67 } 68 dc := &delayedConnection{ 69 l: l, 70 } 71 dc.wg.Add(1) 72 defer func() { 73 if err != nil { 74 dc.Close() 75 } 76 }() 77 p.stdin = dc 78 79 go func() { 80 c.logger.WithFields(logrus.Fields{"stdin": fifos.Stdin}).Debug("accept") 81 conn, err := l.Accept() 82 if err != nil { 83 dc.Close() 84 if err != winio.ErrPipeListenerClosed { 85 c.logger.WithError(err).Errorf("failed to accept stdin connection on %s", fifos.Stdin) 86 } 87 return 88 } 89 c.logger.WithFields(logrus.Fields{"stdin": fifos.Stdin}).Debug("connected") 90 dc.con = conn 91 dc.unblockConnectionWaiters() 92 }() 93 } 94 95 if fifos.Stdout != "" { 96 c.logger.WithFields(logrus.Fields{"stdout": fifos.Stdout}).Debug("listen") 97 l, err := winio.ListenPipe(fifos.Stdout, nil) 98 if err != nil { 99 return nil, errors.Wrapf(err, "failed to create stdout pipe %s", fifos.Stdout) 100 } 101 dc := &delayedConnection{ 102 l: l, 103 } 104 dc.wg.Add(1) 105 defer func() { 106 if err != nil { 107 dc.Close() 108 } 109 }() 110 p.stdout = dc 111 112 go func() { 113 c.logger.WithFields(logrus.Fields{"stdout": fifos.Stdout}).Debug("accept") 114 conn, err := l.Accept() 115 if err != nil { 116 dc.Close() 117 if err != winio.ErrPipeListenerClosed { 118 c.logger.WithError(err).Errorf("failed to accept stdout connection on %s", fifos.Stdout) 119 } 120 return 121 } 122 c.logger.WithFields(logrus.Fields{"stdout": fifos.Stdout}).Debug("connected") 123 dc.con = conn 124 dc.unblockConnectionWaiters() 125 }() 126 } 127 128 if fifos.Stderr != "" { 129 c.logger.WithFields(logrus.Fields{"stderr": fifos.Stderr}).Debug("listen") 130 l, err := winio.ListenPipe(fifos.Stderr, nil) 131 if err != nil { 132 return nil, errors.Wrapf(err, "failed to create stderr pipe %s", fifos.Stderr) 133 } 134 dc := &delayedConnection{ 135 l: l, 136 } 137 dc.wg.Add(1) 138 defer func() { 139 if err != nil { 140 dc.Close() 141 } 142 }() 143 p.stderr = dc 144 145 go func() { 146 c.logger.WithFields(logrus.Fields{"stderr": fifos.Stderr}).Debug("accept") 147 conn, err := l.Accept() 148 if err != nil { 149 dc.Close() 150 if err != winio.ErrPipeListenerClosed { 151 c.logger.WithError(err).Errorf("failed to accept stderr connection on %s", fifos.Stderr) 152 } 153 return 154 } 155 c.logger.WithFields(logrus.Fields{"stderr": fifos.Stderr}).Debug("connected") 156 dc.con = conn 157 dc.unblockConnectionWaiters() 158 }() 159 } 160 return p, nil 161 }