Kaynağa Gözat

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 <david.calavera@gmail.com>
David Calavera 9 yıl önce
ebeveyn
işleme
c4e49d1014
2 değiştirilmiş dosya ile 47 ekleme ve 10 silme
  1. 8 10
      daemon/delete.go
  2. 39 0
      daemon/delete_test.go

+ 8 - 10
daemon/delete.go

@@ -76,22 +76,20 @@ func (daemon *Daemon) rm(container *Container, forceRemove bool) (err error) {
 		}
 		}
 	}
 	}
 
 
-	// 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.
 	// Container state RemovalInProgress should be used to avoid races.
 	if err = container.setRemovalInProgress(); err != nil {
 	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)
 		return derr.ErrorCodeRmState.WithArgs(err)
 	}
 	}
-
 	defer container.resetRemovalInProgress()
 	defer container.resetRemovalInProgress()
 
 
+	// stop collection of stats for the container regardless
+	// if stats are currently getting collected.
+	daemon.statsCollector.stopCollection(container)
+
 	if err = container.Stop(3); err != nil {
 	if err = container.Stop(3); err != nil {
 		return err
 		return err
 	}
 	}

+ 39 - 0
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)
+	}
+}