Merge pull request #25861 from WeiZhang555/wait-remove-for-start

Using waitExitOrRemoved for `docker start`
This commit is contained in:
Alexander Morozov 2016-08-26 13:36:56 -07:00 committed by GitHub
commit bdadcfc1bb
2 changed files with 29 additions and 8 deletions

View file

@ -89,8 +89,8 @@ func runStart(dockerCli *client.DockerCli, opts *startOptions) error {
resp, errAttach := dockerCli.Client().ContainerAttach(ctx, c.ID, options)
if errAttach != nil && errAttach != httputil.ErrPersistEOF {
// ContainerAttach return an ErrPersistEOF (connection closed)
// means server met an error and put it in Hijacked connection
// keep the error and read detailed error message from hijacked connection
// means server met an error and already put it in Hijacked connection,
// we would keep the error and read the detailed error message from hijacked connection
return errAttach
}
defer resp.Close()
@ -102,14 +102,22 @@ func runStart(dockerCli *client.DockerCli, opts *startOptions) error {
return errHijack
})
// 3. Start the container.
// 3. We should open a channel for receiving status code of the container
// no matter it's detached, removed on daemon side(--rm) or exit normally.
statusChan, statusErr := waitExitOrRemoved(dockerCli, context.Background(), c.ID, c.HostConfig.AutoRemove)
// 4. Start the container.
if err := dockerCli.Client().ContainerStart(ctx, c.ID, types.ContainerStartOptions{}); err != nil {
cancelFun()
<-cErr
if c.HostConfig.AutoRemove && statusErr == nil {
// wait container to be removed
<-statusChan
}
return err
}
// 4. Wait for attachment to break.
// 5. Wait for attachment to break.
if c.Config.Tty && dockerCli.IsTerminalOut() {
if err := dockerCli.MonitorTtySize(ctx, c.ID, false); err != nil {
fmt.Fprintf(dockerCli.Err(), "Error monitoring TTY size: %s\n", err)
@ -118,11 +126,12 @@ func runStart(dockerCli *client.DockerCli, opts *startOptions) error {
if attchErr := <-cErr; attchErr != nil {
return attchErr
}
_, status, err := getExitCode(dockerCli, ctx, c.ID)
if err != nil {
return err
if statusErr != nil {
return fmt.Errorf("can't get container's exit code: %v", statusErr)
}
if status != 0 {
if status := <-statusChan; status != 0 {
return cli.StatusError{StatusCode: status}
}
} else {

View file

@ -185,3 +185,15 @@ func (s *DockerSuite) TestStartAttachWithRename(c *check.C) {
_, stderr, _, _ := runCommandWithStdoutStderr(exec.Command(dockerBinary, "start", "-a", "before"))
c.Assert(stderr, checker.Not(checker.Contains), "No such container")
}
func (s *DockerSuite) TestStartReturnCorrectExitCode(c *check.C) {
dockerCmd(c, "create", "--restart=on-failure:2", "--name", "withRestart", "busybox", "sh", "-c", "exit 11")
dockerCmd(c, "create", "--rm", "--name", "withRm", "busybox", "sh", "-c", "exit 12")
_, exitCode, err := dockerCmdWithError("start", "-a", "withRestart")
c.Assert(err, checker.NotNil)
c.Assert(exitCode, checker.Equals, 11)
_, exitCode, err = dockerCmdWithError("start", "-a", "withRm")
c.Assert(err, checker.NotNil)
c.Assert(exitCode, checker.Equals, 12)
}