Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using waitExitOrRemoved for docker start #25861

Merged
merged 1 commit into from
Aug 26, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 17 additions & 8 deletions api/client/container/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,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()
Expand All @@ -103,14 +103,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)
Expand All @@ -119,11 +127,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 {
Expand Down
12 changes: 12 additions & 0 deletions integration-cli/docker_cli_start_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}