diff --git a/internal/lib/sandbox/sandbox.go b/internal/lib/sandbox/sandbox.go index 4f7d76ff210..ef905c960fd 100644 --- a/internal/lib/sandbox/sandbox.go +++ b/internal/lib/sandbox/sandbox.go @@ -103,10 +103,16 @@ func New(id, namespace, name, kubeName, logDir string, labels, annotations map[s } func (s *Sandbox) CRISandbox() *types.PodSandbox { - // Return a deep copy so the State field doesn't get mutated mid-request, - // causing a proto panic. - cpy := *s.criSandbox - return &cpy + // If a protobuf message gets mutated mid-request, then the proto library panics. + // We would like to avoid deep copies when possible to avoid excessive garbage + // collection, but need to if the sandbox changes state. + newState := s.State() + if newState != s.criSandbox.State { + cpy := *s.criSandbox + cpy.State = newState + s.criSandbox = &cpy + } + return s.criSandbox } func (s *Sandbox) CreatedAt() int64 { diff --git a/internal/oci/container.go b/internal/oci/container.go index 1fea6543ff9..4f6c73b1ff4 100644 --- a/internal/oci/container.go +++ b/internal/oci/container.go @@ -169,10 +169,24 @@ func NewSpoofedContainer(id, name string, labels map[string]string, sandbox stri } func (c *Container) CRIContainer() *types.Container { - // Return a deep copy so the State field doesn't get mutated mid-request, - // causing a proto panic. - cpy := *c.criContainer - return &cpy + // If a protobuf message gets mutated mid-request, then the proto library panics. + // We would like to avoid deep copies when possible to avoid excessive garbage + // collection, but need to if the container changes state. + newState := types.ContainerState_CONTAINER_UNKNOWN + switch c.StateNoLock().Status { + case ContainerStateCreated: + newState = types.ContainerState_CONTAINER_CREATED + case ContainerStateRunning, ContainerStatePaused: + newState = types.ContainerState_CONTAINER_RUNNING + case ContainerStateStopped: + newState = types.ContainerState_CONTAINER_EXITED + } + if newState != c.criContainer.State { + cpy := *c.criContainer + cpy.State = newState + c.criContainer = &cpy + } + return c.criContainer } // SetSpec loads the OCI spec in the container struct diff --git a/server/container_list.go b/server/container_list.go index a8219810dee..d126b1ebebd 100644 --- a/server/container_list.go +++ b/server/container_list.go @@ -78,19 +78,6 @@ func (s *Server) ListContainers(ctx context.Context, req *types.ListContainersRe continue } c := ctr.CRIContainer() - cState := ctr.StateNoLock() - - rState := types.ContainerState_CONTAINER_UNKNOWN - switch cState.Status { - case oci.ContainerStateCreated: - rState = types.ContainerState_CONTAINER_CREATED - case oci.ContainerStateRunning, oci.ContainerStatePaused: - rState = types.ContainerState_CONTAINER_RUNNING - case oci.ContainerStateStopped: - rState = types.ContainerState_CONTAINER_EXITED - } - c.State = rState - // Filter by other criteria such as state and labels. if filterContainer(c, req.Filter) { ctrs = append(ctrs, c) diff --git a/server/sandbox_list.go b/server/sandbox_list.go index 23625544f2d..56069b4e6fc 100644 --- a/server/sandbox_list.go +++ b/server/sandbox_list.go @@ -20,8 +20,6 @@ func (s *Server) ListPodSandbox(ctx context.Context, req *types.ListPodSandboxRe } pod := sb.CRISandbox() - pod.State = sb.State() - // Filter by other criteria such as state and labels. if filterSandbox(pod, req.Filter) { respList = append(respList, pod)