Repository: containerd/containerd
File: internal/cri/server/podsandbox/sandbox_stop.go (Go)

Code before:
	"github.com/containerd/errdefs"
	"github.com/containerd/log"

	eventtypes "github.com/containerd/containerd/api/events"
	"github.com/containerd/containerd/v2/core/sandbox"
	"github.com/containerd/containerd/v2/internal/cri/server/podsandbox/types"
	sandboxstore "github.com/containerd/containerd/v2/internal/cri/store/sandbox"
	ctrdutil "github.com/containerd/containerd/v2/internal/cri/util"
	"github.com/containerd/containerd/v2/pkg/protobuf"
)

func (c *Controller) Stop(ctx context.Context, sandboxID string, _ ...sandbox.StopOpt) error {
	podSandbox := c.store.Get(sandboxID)
	if podSandbox == nil {
		return errdefs.ErrNotFound
	}
	if podSandbox.Container == nil {
		return nil
	}
	meta, err := getMetadata(ctx, podSandbox.Container)
	if err != nil {
		return err
	}
	state := podSandbox.Status.Get().State
	if state == sandboxstore.StateReady || state == sandboxstore.StateUnknown {
		if err := c.stopSandboxContainer(ctx, podSandbox); err != nil {
			return fmt.Errorf("failed to stop sandbox container %q in %q state: %w", sandboxID, state, err)
		}
	}
	if err := c.cleanupSandboxFiles(sandboxID, meta.Config); err != nil {
		return fmt.Errorf("failed to cleanup sandbox files: %w", err)
	}
	return nil
}

// stopSandboxContainer kills the sandbox container.
// `task.Delete` is not called here because it will be called when
// the event monitor handles the `TaskExit` event.
func (c *Controller) stopSandboxContainer(ctx context.Context, podSandbox *types.PodSandbox) error {
	id := podSandbox.ID
	container := podSandbox.Container
	state := podSandbox.Status.Get().State
	task, err := container.Task(ctx, nil)
	if err != nil {
		if !errdefs.IsNotFound(err) {
			return fmt.Errorf("failed to get pod sandbox container: %w", err)
		}
		// Don't return for unknown state, some cleanup needs to be done.
		if state == sandboxstore.StateUnknown {
			return cleanupUnknownSandbox(ctx, id, podSandbox)
		}

Review comment (suggestion):
In the `stopSandboxContainer` function, why not treat `ttrpc: closed` as success?

Kill is to terminate the process managed by shim. If shim has exited which indicates the process has ended already.


Code after:
	"github.com/containerd/errdefs"
	"github.com/containerd/log"

	eventtypes "github.com/containerd/containerd/api/events"
	"github.com/containerd/containerd/v2/core/sandbox"
	"github.com/containerd/containerd/v2/internal/cri/server/podsandbox/types"
	sandboxstore "github.com/containerd/containerd/v2/internal/cri/store/sandbox"
	ctrdutil "github.com/containerd/containerd/v2/internal/cri/util"
	"github.com/containerd/containerd/v2/pkg/protobuf"
)

func (c *Controller) Stop(ctx context.Context, sandboxID string, _ ...sandbox.StopOpt) error {
	podSandbox := c.store.Get(sandboxID)
	if podSandbox == nil {
		return errdefs.ErrNotFound
	}
	if podSandbox.Container == nil {
		return nil
	}
	meta, err := getMetadata(ctx, podSandbox.Container)
	if err != nil {
		return err
	}
	state := podSandbox.Status.Get().State
	if state == sandboxstore.StateReady || state == sandboxstore.StateUnknown {
		err = c.stopSandboxContainer(ctx, podSandbox)
		if err != nil && isShimTTRPCClosed(err) {
			log.G(ctx).WithError(err).
				Warnf("Shim ttrpc connection closed when stopping sandbox container %q in %q state, retrying", sandboxID, state)

			err = c.stopSandboxContainer(ctx, podSandbox)
		}
		if err != nil {
			return fmt.Errorf("failed to stop sandbox container %q in %q state: %w", sandboxID, state, err)
		}
	}
	if err := c.cleanupSandboxFiles(sandboxID, meta.Config); err != nil {
		return fmt.Errorf("failed to cleanup sandbox files: %w", err)
	}
	return nil
}

// stopSandboxContainer kills the sandbox container.
// `task.Delete` is not called here because it will be called when
// the event monitor handles the `TaskExit` event.
func (c *Controller) stopSandboxContainer(ctx context.Context, podSandbox *types.PodSandbox) error {
	id := podSandbox.ID
	container := podSandbox.Container
	state := podSandbox.Status.Get().State
	task, err := container.Task(ctx, nil)
	if err != nil {