From 130257f1498ecb1bafe093bad3071ae18a2aff53 Mon Sep 17 00:00:00 2001 From: David Calavera Date: Tue, 20 Oct 2015 16:36:09 -0400 Subject: [PATCH] Do not fail when a container is being removed and we request its delete again. Abort the process and return a success response, letting the original request finish its job. Signed-off-by: David Calavera Upstream-commit: c4e49d10143178c718178ff7ce857f4f8ed46a0b Component: engine --- components/engine/daemon/delete.go | 22 +++++++------- components/engine/daemon/delete_test.go | 39 +++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 12 deletions(-) create mode 100644 components/engine/daemon/delete_test.go diff --git a/components/engine/daemon/delete.go b/components/engine/daemon/delete.go index 52cc39beaf..49ccc72779 100644 --- a/components/engine/daemon/delete.go +++ b/components/engine/daemon/delete.go @@ -76,22 +76,20 @@ func (daemon *Daemon) rm(container *Container, forceRemove bool) (err error) { } } + // Container state RemovalInProgress should be used to avoid races. + if err = container.setRemovalInProgress(); err != nil { + if err == derr.ErrorCodeAlreadyRemoving { + // do not fail when the removal is in progress started by other request. + return nil + } + return derr.ErrorCodeRmState.WithArgs(err) + } + defer container.resetRemovalInProgress() + // stop collection of stats for the container regardless // if stats are currently getting collected. daemon.statsCollector.stopCollection(container) - element := daemon.containers.Get(container.ID) - if element == nil { - return derr.ErrorCodeRmNotFound.WithArgs(container.ID) - } - - // Container state RemovalInProgress should be used to avoid races. - if err = container.setRemovalInProgress(); err != nil { - return derr.ErrorCodeRmState.WithArgs(err) - } - - defer container.resetRemovalInProgress() - if err = container.Stop(3); err != nil { return err } diff --git a/components/engine/daemon/delete_test.go b/components/engine/daemon/delete_test.go new file mode 100644 index 0000000000..9a82fce2d2 --- /dev/null +++ b/components/engine/daemon/delete_test.go @@ -0,0 +1,39 @@ +package daemon + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/docker/docker/runconfig" +) + +func TestContainerDoubleDelete(t *testing.T) { + tmp, err := ioutil.TempDir("", "docker-daemon-unix-test-") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(tmp) + daemon := &Daemon{ + repository: tmp, + root: tmp, + } + + container := &Container{ + CommonContainer: CommonContainer{ + State: NewState(), + Config: &runconfig.Config{}, + }, + } + + // Mark the container as having a delete in progress + if err := container.setRemovalInProgress(); err != nil { + t.Fatal(err) + } + + // Try to remove the container when it's start is removalInProgress. + // It should ignore the container and not return an error. + if err := daemon.rm(container, true); err != nil { + t.Fatal(err) + } +}