mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
9ae9d4c87a
Signed-off-by: John Howard <jhoward@microsoft.com>
82 lines
3 KiB
Go
82 lines
3 KiB
Go
// +build windows
|
|
|
|
package windows
|
|
|
|
import (
|
|
"io"
|
|
|
|
"github.com/Sirupsen/logrus"
|
|
"github.com/natefinch/npipe"
|
|
)
|
|
|
|
// stdinAccept runs as a go function. It waits for the container system
|
|
// to accept our offer of a named pipe for stdin. Once accepted, if we are
|
|
// running "attached" to the container (eg docker run -i), then we spin up
|
|
// a further thread to copy anything from the client into the container.
|
|
//
|
|
// Important design note. This function is run as a go function for a very
|
|
// good reason. The named pipe Accept call is blocking until one of two things
|
|
// happen. Either someone connects to it, or it is forcibly closed. Let's
|
|
// assume that no-one connects to it, the only way otherwise the Run()
|
|
// method would continue is by closing it. However, as that would be the same
|
|
// thread, it can't close it. Hence we run as another thread allowing Run()
|
|
// to close the named pipe.
|
|
func stdinAccept(inListen *npipe.PipeListener, pipeName string, copyfrom io.ReadCloser) {
|
|
|
|
// Wait for the pipe to be connected to by the shim
|
|
logrus.Debugln("stdinAccept: Waiting on ", pipeName)
|
|
stdinConn, err := inListen.Accept()
|
|
if err != nil {
|
|
logrus.Errorf("Failed to accept on pipe %s %s", pipeName, err)
|
|
return
|
|
}
|
|
logrus.Debugln("Connected to ", stdinConn.RemoteAddr())
|
|
|
|
// Anything that comes from the client stdin should be copied
|
|
// across to the stdin named pipe of the container.
|
|
if copyfrom != nil {
|
|
go func() {
|
|
defer stdinConn.Close()
|
|
logrus.Debugln("Calling io.Copy on stdin")
|
|
bytes, err := io.Copy(stdinConn, copyfrom)
|
|
logrus.Debugf("Finished io.Copy on stdin bytes=%d err=%s pipe=%s", bytes, err, stdinConn.RemoteAddr())
|
|
}()
|
|
} else {
|
|
defer stdinConn.Close()
|
|
}
|
|
}
|
|
|
|
// stdouterrAccept runs as a go function. It waits for the container system to
|
|
// accept our offer of a named pipe - in fact two of them - one for stdout
|
|
// and one for stderr (we are called twice). Once the named pipe is accepted,
|
|
// if we are running "attached" to the container (eg docker run -i), then we
|
|
// spin up a further thread to copy anything from the containers output channels
|
|
// to the client.
|
|
func stdouterrAccept(outerrListen *npipe.PipeListener, pipeName string, copyto io.Writer) {
|
|
|
|
// Wait for the pipe to be connected to by the shim
|
|
logrus.Debugln("out/err: Waiting on ", pipeName)
|
|
outerrConn, err := outerrListen.Accept()
|
|
if err != nil {
|
|
logrus.Errorf("Failed to accept on pipe %s %s", pipeName, err)
|
|
return
|
|
}
|
|
logrus.Debugln("Connected to ", outerrConn.RemoteAddr())
|
|
|
|
// Anything that comes from the container named pipe stdout/err should be copied
|
|
// across to the stdout/err of the client
|
|
if copyto != nil {
|
|
go func() {
|
|
defer outerrConn.Close()
|
|
logrus.Debugln("Calling io.Copy on ", pipeName)
|
|
bytes, err := io.Copy(copyto, outerrConn)
|
|
logrus.Debugf("Copied %d bytes from pipe=%s", bytes, outerrConn.RemoteAddr())
|
|
if err != nil {
|
|
// Not fatal, just debug log it
|
|
logrus.Debugf("Error hit during copy %s", err)
|
|
}
|
|
}()
|
|
} else {
|
|
defer outerrConn.Close()
|
|
}
|
|
}
|