Repository: moby/moby
File: daemon/delete.go (Go)

Code before:
	}

	// Mark container dead. We don't want anybody to be restarting it.
	container.Lock()
	container.Dead = true

	// Save container state to disk. So that if error happens before
	// container meta file got removed from disk, then a restart of
	// docker should not make a dead container alive.
	if err := container.CheckpointTo(context.WithoutCancel(context.TODO()), daemon.containersReplica); err != nil && !os.IsNotExist(err) {
		log.G(context.TODO()).Errorf("Error saving dying container to disk: %v", err)
	}
	container.Unlock()

	// When container creation fails and `RWLayer` has not been created yet, we
	// do not call `ReleaseRWLayer`
	if container.RWLayer != nil {
		if err := daemon.imageService.ReleaseLayer(container.RWLayer); err != nil {
			err = errors.Wrapf(err, "container %s", container.ID)
			container.SetRemovalError(err)
			return err
		}
		// Hold the container lock while clearing RWLayer reference to avoid dereferencing nil in other places.
		container.Lock()
		container.RWLayer = nil
		container.Unlock()
	} else {
		if daemon.UsesSnapshotter() {
			ls := daemon.containerdClient.LeasesService()
			lease := leases.Lease{
				ID: container.ID,
			}
			if err := ls.Delete(context.Background(), lease, leases.SynchronousDelete); err != nil {
				if !cerrdefs.IsNotFound(err) {
					container.SetRemovalError(err)
					return err
				}
			}
		}
	}

	// Hold the container lock while deleting the container root directory
	// so that other goroutines don't attempt to concurrently open files
	// within it. Having any file open on Windows (without the
	// FILE_SHARE_DELETE flag) will block it from being deleted.
	//
	// TODO(thaJeztah): should this be moved to the "container" itself, or possibly be delegated to the graphdriver or snapshotter?
	container.Lock()
	err := containerfs.EnsureRemoveAll(container.Root)
	container.Unlock()
	if err != nil {

Review comment (performance):
It's probably a bit inefficient as right after this if-else statement a lock is acquired again. But I'm not sure if it's worth to avoid an extra locking as the code would get more complicated. WDYT?

Code after:
	}

	// Mark container dead. We don't want anybody to be restarting it.
	container.Lock()
	container.Dead = true

	// Copy RWLayer for releasing and clear the reference while holding the container lock.
	rwLayer := container.RWLayer
	container.RWLayer = nil

	// Save container state to disk. So that if error happens before
	// container meta file got removed from disk, then a restart of
	// docker should not make a dead container alive.
	if err := container.CheckpointTo(context.WithoutCancel(context.TODO()), daemon.containersReplica); err != nil && !os.IsNotExist(err) {
		log.G(context.TODO()).Errorf("Error saving dying container to disk: %v", err)
	}
	container.Unlock()

	// When container creation fails and `RWLayer` has not been created yet, we
	// do not call `ReleaseRWLayer`
	if rwLayer != nil {
		if err := daemon.imageService.ReleaseLayer(rwLayer); err != nil {
			// Restore the reference on error as it possibly was not released.
			container.Lock()
			container.RWLayer = rwLayer
			container.Unlock()

			err = errors.Wrapf(err, "container %s", container.ID)
			container.SetRemovalError(err)
			return err
		}
	} else {
		if daemon.UsesSnapshotter() {
			ls := daemon.containerdClient.LeasesService()
			lease := leases.Lease{
				ID: container.ID,
			}
			if err := ls.Delete(context.Background(), lease, leases.SynchronousDelete); err != nil {
				if !cerrdefs.IsNotFound(err) {
					container.SetRemovalError(err)
					return err
				}
			}
		}
	}

	// Hold the container lock while deleting the container root directory
	// so that other goroutines don't attempt to concurrently open files
	// within it. Having any file open on Windows (without the
	// FILE_SHARE_DELETE flag) will block it from being deleted.
	//