1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Bug fix: docker run -i --restart always hangs.

e.g.
```
$ docker run -i --restart always busybox sh
pwd
/
exit 11

<...hang...>
```

This is because Attach(daemon side) and Run(client side) both hangs on
WaitStop, if container is restarted too quickly, wait won't have chance
to get exit signal.

Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
This commit is contained in:
Zhang Wei 2016-05-17 10:30:06 +08:00
parent e94be2f639
commit c498d4700d
3 changed files with 42 additions and 2 deletions

View file

@ -287,7 +287,7 @@ func runRun(dockerCli *client.DockerCli, flags *pflag.FlagSet, opts *runOptions,
}
} else {
// No Autoremove: Simply retrieve the exit code
if !config.Tty {
if !config.Tty && hostConfig.RestartPolicy.IsNone() {
// In non-TTY mode, we can't detach, so we must wait for container exit
if status, err = client.ContainerWait(ctx, createResponse.ID); err != nil {
return err

View file

@ -119,6 +119,15 @@ func (daemon *Daemon) containerAttach(c *container.Container, stdin io.ReadClose
}()
stdinPipe = r
}
waitChan := make(chan struct{})
if c.Config.StdinOnce && !c.Config.Tty {
go func() {
c.WaitStop(-1 * time.Second)
close(waitChan)
}()
}
err := <-c.Attach(stdinPipe, stdout, stderr, keys)
if err != nil {
if _, ok := err.(container.DetachError); ok {
@ -131,7 +140,7 @@ func (daemon *Daemon) containerAttach(c *container.Container, stdin io.ReadClose
// If we are in stdinonce mode, wait for the process to end
// otherwise, simply return
if c.Config.StdinOnce && !c.Config.Tty {
c.WaitStop(-1 * time.Second)
<-waitChan
}
}
return nil

View file

@ -1828,6 +1828,37 @@ func (s *DockerSuite) TestRunExitOnStdinClose(c *check.C) {
}
}
// Test run -i --restart xxx doesn't hang
func (s *DockerSuite) TestRunInteractiveWithRestartPolicy(c *check.C) {
name := "test-inter-restart"
runCmd := exec.Command(dockerBinary, "run", "-i", "--name", name, "--restart=always", "busybox", "sh")
stdin, err := runCmd.StdinPipe()
c.Assert(err, checker.IsNil)
err = runCmd.Start()
c.Assert(err, checker.IsNil)
c.Assert(waitRun(name), check.IsNil)
_, err = stdin.Write([]byte("exit 11\n"))
c.Assert(err, checker.IsNil)
finish := make(chan error)
go func() {
finish <- runCmd.Wait()
close(finish)
}()
delay := 10 * time.Second
select {
case <-finish:
case <-time.After(delay):
c.Fatal("run -i --restart hangs")
}
c.Assert(waitRun(name), check.IsNil)
dockerCmd(c, "stop", name)
}
// Test for #2267
func (s *DockerSuite) TestRunWriteHostsFileAndNotCommit(c *check.C) {
// Cannot run on Windows as Windows does not support diff.