@@ -31,6 +31,7 @@ import (
3131 "github.com/docker/docker/pkg/ioutils"
3232 "github.com/docker/docker/pkg/longpath"
3333 "github.com/docker/docker/pkg/reexec"
34+ "github.com/docker/docker/pkg/system"
3435 units "github.com/docker/go-units"
3536 "golang.org/x/sys/windows"
3637)
@@ -265,19 +266,35 @@ func (d *Driver) Remove(id string) error {
265266 // it is a transient error. Retry until it succeeds.
266267 var computeSystems []hcsshim.ContainerProperties
267268 retryCount := 0
269+ osv := system .GetOSVersion ()
268270 for {
269- // Get and terminate any template VMs that are currently using the layer
271+ // Get and terminate any template VMs that are currently using the layer.
272+ // Note: It is unfortunate that we end up in the graphdrivers Remove() call
273+ // for both containers and images, but the logic for template VMs is only
274+ // needed for images - specifically we are looking to see if a base layer
275+ // is in use by a template VM as a result of having started a Hyper-V
276+ // container at some point.
277+ //
278+ // We have a retry loop for ErrVmcomputeOperationInvalidState and
279+ // ErrVmcomputeOperationAccessIsDenied as there is a race condition
280+ // in RS1 and RS2 building during enumeration when a silo is going away
281+ // for example under it, in HCS. AccessIsDenied added to fix 30278.
282+ //
283+ // TODO @jhowardmsft - For RS3, we can remove the retries. Also consider
284+ // using platform APIs (if available) to get this more succinctly. Also
285+ // consider enlighting the Remove() interface to have context of why
286+ // the remove is being called - that could improve efficiency by not
287+ // enumerating compute systems during a remove of a container as it's
288+ // not required.
270289 computeSystems , err = hcsshim .GetContainers (hcsshim.ComputeSystemQuery {})
271290 if err != nil {
272- if err == hcsshim .ErrVmcomputeOperationInvalidState {
273- if retryCount >= 5 {
274- // If we are unable to get the list of containers
275- // go ahead and attempt to delete the layer anyway
276- // as it will most likely work.
291+ if (osv .Build < 15139 ) &&
292+ ((err == hcsshim .ErrVmcomputeOperationInvalidState ) || (err == hcsshim .ErrVmcomputeOperationAccessIsDenied )) {
293+ if retryCount >= 500 {
277294 break
278295 }
279296 retryCount ++
280- time .Sleep (2 * time .Second )
297+ time .Sleep (10 * time .Millisecond )
281298 continue
282299 }
283300 return err
0 commit comments