fix(container): handle race condition on ContainerWait
When a destination is removed, its container is stopped and removed. This preempts the ContainerWait call in the destination loop, which then tries to call ContainerInspect to infer if the container is restarting or not. It was already known that this call is prone to race conditions. This commit handles an additional case where the container has already been completely removed by the time the call is made; we can safely infer that it is not restarting.
This commit is contained in:
parent
b508632e70
commit
ffce32f4fe
@ -21,6 +21,7 @@ import (
|
|||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/api/types/image"
|
"github.com/docker/docker/api/types/image"
|
||||||
"github.com/docker/docker/api/types/network"
|
"github.com/docker/docker/api/types/network"
|
||||||
|
"github.com/docker/docker/errdefs"
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -338,17 +339,21 @@ func (a *Client) runContainerLoop(
|
|||||||
respC, errC := a.apiClient.ContainerWait(ctx, containerID, container.WaitConditionNextExit)
|
respC, errC := a.apiClient.ContainerWait(ctx, containerID, container.WaitConditionNextExit)
|
||||||
select {
|
select {
|
||||||
case resp := <-respC:
|
case resp := <-respC:
|
||||||
|
var restarting bool
|
||||||
// Check if the container is restarting. If it is not then we don't
|
// Check if the container is restarting. If it is not then we don't
|
||||||
// want to wait for it again and can return early.
|
// want to wait for it again and can return early.
|
||||||
ctr, err := a.apiClient.ContainerInspect(ctx, containerID)
|
ctr, err := a.apiClient.ContainerInspect(ctx, containerID)
|
||||||
if err != nil {
|
// Race conidition: the container may already have been removed.
|
||||||
|
if errdefs.IsNotFound(err) {
|
||||||
|
// ignore error but do not restart
|
||||||
|
} else if err != nil {
|
||||||
a.logger.Error("Error inspecting container", "err", err, "id", shortID(containerID))
|
a.logger.Error("Error inspecting container", "err", err, "id", shortID(containerID))
|
||||||
containerErrC <- err
|
containerErrC <- err
|
||||||
return
|
return
|
||||||
}
|
|
||||||
|
|
||||||
// Race condition: the container may have already restarted.
|
// Race condition: the container may have already restarted.
|
||||||
restarting := ctr.State.Status == domain.ContainerStatusRestarting || ctr.State.Status == domain.ContainerStatusRunning
|
} else if ctr.State.Status == domain.ContainerStatusRestarting || ctr.State.Status == domain.ContainerStatusRunning {
|
||||||
|
restarting = true
|
||||||
|
}
|
||||||
|
|
||||||
containerRespC <- containerWaitResponse{WaitResponse: resp, restarting: restarting}
|
containerRespC <- containerWaitResponse{WaitResponse: resp, restarting: restarting}
|
||||||
if !restarting {
|
if !restarting {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user