Browse Source

Merge pull request #22777 from WeiZhang555/wait-restarting

Bug fix: `docker run -i --restart always` hangs
Vincent Demeester 9 years ago
parent
commit
4dafd107ad
3 changed files with 42 additions and 2 deletions
  1. 1 1
      api/client/container/run.go
  2. 10 1
      daemon/attach.go
  3. 31 0
      integration-cli/docker_cli_run_test.go

+ 1 - 1
api/client/container/run.go

@@ -288,7 +288,7 @@ func runRun(dockerCli *client.DockerCli, flags *pflag.FlagSet, opts *runOptions,
 		}
 		}
 	} else {
 	} else {
 		// No Autoremove: Simply retrieve the exit code
 		// 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
 			// 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 {
 			if status, err = client.ContainerWait(ctx, createResponse.ID); err != nil {
 				return err
 				return err

+ 10 - 1
daemon/attach.go

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

+ 31 - 0
integration-cli/docker_cli_run_test.go

@@ -1833,6 +1833,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
 // Test for #2267
 func (s *DockerSuite) TestRunWriteHostsFileAndNotCommit(c *check.C) {
 func (s *DockerSuite) TestRunWriteHostsFileAndNotCommit(c *check.C) {
 	// Cannot run on Windows as Windows does not support diff.
 	// Cannot run on Windows as Windows does not support diff.