diff --git a/daemon/exec.go b/daemon/exec.go index 1151a77c7bb50..08b6ac46ffcd3 100644 --- a/daemon/exec.go +++ b/daemon/exec.go @@ -157,7 +157,7 @@ func (d *Daemon) ContainerExecStart(name string, stdin io.ReadCloser, stdout io. logrus.Debugf("starting exec command %s in container %s", ec.ID, c.ID) d.LogContainerEvent(c, "exec_start: "+ec.ProcessConfig.Entrypoint+" "+strings.Join(ec.ProcessConfig.Arguments, " ")) - if ec.OpenStdin { + if ec.OpenStdin && stdin != nil { r, w := io.Pipe() go func() { defer w.Close() diff --git a/integration-cli/docker_api_exec_test.go b/integration-cli/docker_api_exec_test.go index 51533223c72ca..0c41687c9cf78 100644 --- a/integration-cli/docker_api_exec_test.go +++ b/integration-cli/docker_api_exec_test.go @@ -122,6 +122,36 @@ func (s *DockerSuite) TestExecApiStartMultipleTimesError(c *check.C) { startExec(c, execID, http.StatusConflict) } +// #20638 +func (s *DockerSuite) TestExecApiStartWithDetach(c *check.C) { + name := "foo" + dockerCmd(c, "run", "-d", "-t", "--name", name, "busybox", "top") + data := map[string]interface{}{ + "cmd": []string{"true"}, + "AttachStdin": true, + } + _, b, err := sockRequest("POST", fmt.Sprintf("/containers/%s/exec", name), data) + c.Assert(err, checker.IsNil, check.Commentf(string(b))) + + createResp := struct { + ID string `json:"Id"` + }{} + c.Assert(json.Unmarshal(b, &createResp), checker.IsNil, check.Commentf(string(b))) + + _, body, err := sockRequestRaw("POST", fmt.Sprintf("/exec/%s/start", createResp.ID), strings.NewReader(`{"Detach": true}`), "application/json") + c.Assert(err, checker.IsNil) + + b, err = readBody(body) + comment := check.Commentf("response body: %s", b) + c.Assert(err, checker.IsNil, comment) + + resp, _, err := sockRequestRaw("GET", "/_ping", nil, "") + c.Assert(err, checker.IsNil) + if resp.StatusCode != http.StatusOK { + c.Fatal("daemon is down, it should alive") + } +} + func createExec(c *check.C, name string) string { _, b, err := sockRequest("POST", fmt.Sprintf("/containers/%s/exec", name), map[string]interface{}{"Cmd": []string{"true"}}) c.Assert(err, checker.IsNil, check.Commentf(string(b)))