Browse code

Merge pull request #22777 from WeiZhang555/wait-restarting

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

Vincent Demeester authored on 2016/06/12 20:01:20
Showing 3 changed files
... ...
@@ -288,7 +288,7 @@ func runRun(dockerCli *client.DockerCli, flags *pflag.FlagSet, opts *runOptions,
288 288
 		}
289 289
 	} else {
290 290
 		// No Autoremove: Simply retrieve the exit code
291
-		if !config.Tty {
291
+		if !config.Tty && hostConfig.RestartPolicy.IsNone() {
292 292
 			// In non-TTY mode, we can't detach, so we must wait for container exit
293 293
 			if status, err = client.ContainerWait(ctx, createResponse.ID); err != nil {
294 294
 				return err
... ...
@@ -119,6 +119,15 @@ func (daemon *Daemon) containerAttach(c *container.Container, stdin io.ReadClose
119 119
 			}()
120 120
 			stdinPipe = r
121 121
 		}
122
+
123
+		waitChan := make(chan struct{})
124
+		if c.Config.StdinOnce && !c.Config.Tty {
125
+			go func() {
126
+				c.WaitStop(-1 * time.Second)
127
+				close(waitChan)
128
+			}()
129
+		}
130
+
122 131
 		err := <-c.Attach(stdinPipe, stdout, stderr, keys)
123 132
 		if err != nil {
124 133
 			if _, ok := err.(container.DetachError); ok {
... ...
@@ -131,7 +140,7 @@ func (daemon *Daemon) containerAttach(c *container.Container, stdin io.ReadClose
131 131
 		// If we are in stdinonce mode, wait for the process to end
132 132
 		// otherwise, simply return
133 133
 		if c.Config.StdinOnce && !c.Config.Tty {
134
-			c.WaitStop(-1 * time.Second)
134
+			<-waitChan
135 135
 		}
136 136
 	}
137 137
 	return nil
... ...
@@ -1833,6 +1833,37 @@ func (s *DockerSuite) TestRunExitOnStdinClose(c *check.C) {
1833 1833
 	}
1834 1834
 }
1835 1835
 
1836
+// Test run -i --restart xxx doesn't hang
1837
+func (s *DockerSuite) TestRunInteractiveWithRestartPolicy(c *check.C) {
1838
+	name := "test-inter-restart"
1839
+	runCmd := exec.Command(dockerBinary, "run", "-i", "--name", name, "--restart=always", "busybox", "sh")
1840
+
1841
+	stdin, err := runCmd.StdinPipe()
1842
+	c.Assert(err, checker.IsNil)
1843
+
1844
+	err = runCmd.Start()
1845
+	c.Assert(err, checker.IsNil)
1846
+	c.Assert(waitRun(name), check.IsNil)
1847
+
1848
+	_, err = stdin.Write([]byte("exit 11\n"))
1849
+	c.Assert(err, checker.IsNil)
1850
+
1851
+	finish := make(chan error)
1852
+	go func() {
1853
+		finish <- runCmd.Wait()
1854
+		close(finish)
1855
+	}()
1856
+	delay := 10 * time.Second
1857
+	select {
1858
+	case <-finish:
1859
+	case <-time.After(delay):
1860
+		c.Fatal("run -i --restart hangs")
1861
+	}
1862
+
1863
+	c.Assert(waitRun(name), check.IsNil)
1864
+	dockerCmd(c, "stop", name)
1865
+}
1866
+
1836 1867
 // Test for #2267
1837 1868
 func (s *DockerSuite) TestRunWriteHostsFileAndNotCommit(c *check.C) {
1838 1869
 	// Cannot run on Windows as Windows does not support diff.