mirror of https://github.com/docker/docs.git
Fix race between two ContainerRm
Signed-off-by: Alexander Morozov <lk4d4@docker.com>
This commit is contained in:
parent
e75da4b6ff
commit
4d1007d75c
|
@ -76,7 +76,7 @@ func (daemon *Daemon) create(params *ContainerCreateConfig) (retC *Container, re
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if retErr != nil {
|
if retErr != nil {
|
||||||
if err := daemon.rm(container, true); err != nil {
|
if err := daemon.ContainerRm(container.ID, &ContainerRmConfig{ForceRemove: true}); err != nil {
|
||||||
logrus.Errorf("Clean up Error! Cannot destroy container %s: %v", container.ID, err)
|
logrus.Errorf("Clean up Error! Cannot destroy container %s: %v", container.ID, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,21 @@ func (daemon *Daemon) ContainerRm(name string, config *ContainerRmConfig) error
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
|
||||||
|
// check if container wasn't deregistered by previous rm since Get
|
||||||
|
if c := daemon.containers.Get(container.ID); c == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if config.RemoveLink {
|
if config.RemoveLink {
|
||||||
name, err := GetFullContainerName(name)
|
name, err := GetFullContainerName(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -76,16 +91,6 @@ 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
|
// stop collection of stats for the container regardless
|
||||||
// if stats are currently getting collected.
|
// if stats are currently getting collected.
|
||||||
daemon.statsCollector.stopCollection(container)
|
daemon.statsCollector.stopCollection(container)
|
||||||
|
|
|
@ -18,13 +18,16 @@ func TestContainerDoubleDelete(t *testing.T) {
|
||||||
repository: tmp,
|
repository: tmp,
|
||||||
root: tmp,
|
root: tmp,
|
||||||
}
|
}
|
||||||
|
daemon.containers = &contStore{s: make(map[string]*Container)}
|
||||||
|
|
||||||
container := &Container{
|
container := &Container{
|
||||||
CommonContainer: CommonContainer{
|
CommonContainer: CommonContainer{
|
||||||
|
ID: "test",
|
||||||
State: NewState(),
|
State: NewState(),
|
||||||
Config: &runconfig.Config{},
|
Config: &runconfig.Config{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
daemon.containers.Add(container.ID, container)
|
||||||
|
|
||||||
// Mark the container as having a delete in progress
|
// Mark the container as having a delete in progress
|
||||||
if err := container.setRemovalInProgress(); err != nil {
|
if err := container.setRemovalInProgress(); err != nil {
|
||||||
|
@ -33,7 +36,7 @@ func TestContainerDoubleDelete(t *testing.T) {
|
||||||
|
|
||||||
// Try to remove the container when it's start is removalInProgress.
|
// Try to remove the container when it's start is removalInProgress.
|
||||||
// It should ignore the container and not return an error.
|
// It should ignore the container and not return an error.
|
||||||
if err := daemon.rm(container, true); err != nil {
|
if err := daemon.ContainerRm(container.ID, &ContainerRmConfig{ForceRemove: true}); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue