diff --git a/daemon/execdriver/native/driver.go b/daemon/execdriver/native/driver.go index d31e159704..c363c3ff5d 100644 --- a/daemon/execdriver/native/driver.go +++ b/daemon/execdriver/native/driver.go @@ -315,6 +315,9 @@ func (d *driver) Clean(id string) error { func (d *driver) Stats(id string) (*execdriver.ResourceStats, error) { c := d.activeContainers[id] + if c == nil { + return nil, execdriver.ErrNotRunning + } now := time.Now() stats, err := c.Stats() if err != nil { diff --git a/integration-cli/docker_api_containers_test.go b/integration-cli/docker_api_containers_test.go index a8746056f1..e717eca574 100644 --- a/integration-cli/docker_api_containers_test.go +++ b/integration-cli/docker_api_containers_test.go @@ -307,7 +307,7 @@ func TestGetContainerStats(t *testing.T) { t.Fatal("stream was not closed after container was removed") case sr := <-bc: if sr.err != nil { - t.Fatal(err) + t.Fatal(sr.err) } dec := json.NewDecoder(bytes.NewBuffer(sr.body)) @@ -320,6 +320,32 @@ func TestGetContainerStats(t *testing.T) { logDone("container REST API - check GET containers/stats") } +func TestGetStoppedContainerStats(t *testing.T) { + defer deleteAllContainers() + var ( + name = "statscontainer" + runCmd = exec.Command(dockerBinary, "create", "--name", name, "busybox", "top") + ) + out, _, err := runCommandWithOutput(runCmd) + if err != nil { + t.Fatalf("Error on container creation: %v, output: %q", err, out) + } + + go func() { + // We'll never get return for GET stats from sockRequest as of now, + // just send request and see if panic or error would happen on daemon side. + _, err := sockRequest("GET", "/containers/"+name+"/stats", nil) + if err != nil { + t.Fatal(err) + } + }() + + // allow some time to send request and let daemon deal with it + time.Sleep(1 * time.Second) + + logDone("container REST API - check GET stopped containers/stats") +} + func TestBuildApiDockerfilePath(t *testing.T) { // Test to make sure we stop people from trying to leave the // build context when specifying the path to the dockerfile