diff --git a/daemon/exec.go b/daemon/exec.go index 54b3e1d527..41e27bc068 100644 --- a/daemon/exec.go +++ b/daemon/exec.go @@ -89,7 +89,16 @@ func (d *Daemon) registerExecCommand(execConfig *execConfig) { } func (d *Daemon) getExecConfig(name string) (*execConfig, error) { - if execConfig := d.execCommands.Get(name); execConfig != nil { + execConfig := d.execCommands.Get(name) + + // If the exec is found but its container is not in the daemon's list of + // containers then it must have been delete, in which case instead of + // saying the container isn't running, we should return a 404 so that + // the user sees the same error now that they will after the + // 5 minute clean-up loop is run which erases old/dead execs. + + if execConfig != nil && d.containers.Get(execConfig.Container.ID) != nil { + if !execConfig.Container.IsRunning() { return nil, fmt.Errorf("Container %s is not running", execConfig.Container.ID) } diff --git a/integration-cli/docker_cli_exec_test.go b/integration-cli/docker_cli_exec_test.go index c9d49766d2..104a1dd3b1 100644 --- a/integration-cli/docker_cli_exec_test.go +++ b/integration-cli/docker_cli_exec_test.go @@ -369,6 +369,17 @@ func (s *DockerSuite) TestInspectExecID(c *check.C) { if sc != http.StatusOK { c.Fatalf("received status != 200 OK: %d\n%s", sc, body) } + + // Now delete the container and then an 'inspect' on the exec should + // result in a 404 (not 'container not running') + out, ec := dockerCmd(c, "rm", "-f", id) + if ec != 0 { + c.Fatalf("error removing container: %s", out) + } + sc, body, err = sockRequest("GET", "/exec/"+execID+"/json", nil) + if sc != http.StatusNotFound { + c.Fatalf("received status != 404: %s\n%s", sc, body) + } } func (s *DockerSuite) TestLinksPingLinkedContainersOnRename(c *check.C) {