mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #16289 from cpuguy83/11957_fix_stdin_block_after_container_exit
Ensure stdin does not block after container stop
This commit is contained in:
commit
c0c941627a
2 changed files with 42 additions and 25 deletions
|
@ -16,7 +16,6 @@ import (
|
|||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/api"
|
||||
"github.com/docker/docker/autogen/dockerversion"
|
||||
"github.com/docker/docker/pkg/promise"
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
"github.com/docker/docker/pkg/term"
|
||||
)
|
||||
|
@ -186,8 +185,6 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.Rea
|
|||
started <- rwc
|
||||
}
|
||||
|
||||
var receiveStdout chan error
|
||||
|
||||
var oldState *term.State
|
||||
|
||||
if in != nil && setRawTerminal && cli.isTerminalIn && os.Getenv("NORAW") == "" {
|
||||
|
@ -198,19 +195,15 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.Rea
|
|||
defer term.RestoreTerminal(cli.inFd, oldState)
|
||||
}
|
||||
|
||||
receiveStdout := make(chan error, 1)
|
||||
if stdout != nil || stderr != nil {
|
||||
receiveStdout = promise.Go(func() (err error) {
|
||||
go func() {
|
||||
defer func() {
|
||||
if in != nil {
|
||||
if setRawTerminal && cli.isTerminalIn {
|
||||
term.RestoreTerminal(cli.inFd, oldState)
|
||||
}
|
||||
// For some reason this Close call blocks on darwin..
|
||||
// As the client exists right after, simply discard the close
|
||||
// until we find a better solution.
|
||||
if runtime.GOOS != "darwin" {
|
||||
in.Close()
|
||||
}
|
||||
in.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -221,11 +214,12 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.Rea
|
|||
_, err = stdcopy.StdCopy(stdout, stderr, br)
|
||||
}
|
||||
logrus.Debugf("[hijack] End of stdout")
|
||||
return err
|
||||
})
|
||||
receiveStdout <- err
|
||||
}()
|
||||
}
|
||||
|
||||
sendStdin := promise.Go(func() error {
|
||||
stdinDone := make(chan struct{})
|
||||
go func() {
|
||||
if in != nil {
|
||||
io.Copy(rwc, in)
|
||||
logrus.Debugf("[hijack] End of stdin")
|
||||
|
@ -238,22 +232,24 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.Rea
|
|||
logrus.Debugf("Couldn't send EOF: %s", err)
|
||||
}
|
||||
}
|
||||
// Discard errors due to pipe interruption
|
||||
return nil
|
||||
})
|
||||
close(stdinDone)
|
||||
}()
|
||||
|
||||
if stdout != nil || stderr != nil {
|
||||
if err := <-receiveStdout; err != nil {
|
||||
select {
|
||||
case err := <-receiveStdout:
|
||||
if err != nil {
|
||||
logrus.Debugf("Error receiveStdout: %s", err)
|
||||
return err
|
||||
}
|
||||
if cli.isTerminalIn {
|
||||
return nil
|
||||
}
|
||||
case <-stdinDone:
|
||||
if stdout != nil || stderr != nil {
|
||||
if err := <-receiveStdout; err != nil {
|
||||
logrus.Debugf("Error receiveStdout: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !cli.isTerminalIn {
|
||||
if err := <-sendStdin; err != nil {
|
||||
logrus.Debugf("Error sendStdin: %s", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -3384,3 +3384,24 @@ func (s *DockerSuite) TestTwoContainersInNetHost(c *check.C) {
|
|||
dockerCmd(c, "stop", "first")
|
||||
dockerCmd(c, "stop", "second")
|
||||
}
|
||||
|
||||
// #11957 - stdin with no tty does not exit if stdin is not closed even though container exited
|
||||
func (s *DockerSuite) TestRunStdinBlockedAfterContainerExit(c *check.C) {
|
||||
cmd := exec.Command(dockerBinary, "run", "-i", "--name=test", "busybox", "true")
|
||||
in, err := cmd.StdinPipe()
|
||||
c.Assert(err, check.IsNil)
|
||||
defer in.Close()
|
||||
c.Assert(cmd.Start(), check.IsNil)
|
||||
|
||||
waitChan := make(chan error)
|
||||
go func() {
|
||||
waitChan <- cmd.Wait()
|
||||
}()
|
||||
|
||||
select {
|
||||
case err := <-waitChan:
|
||||
c.Assert(err, check.IsNil)
|
||||
case <-time.After(3 * time.Second):
|
||||
c.Fatal("timeout waiting for command to exit")
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue