diff --git a/cgroup/cgroup_test.go b/cgroup/cgroup_test.go index 4ac82cdf..d9145a07 100644 --- a/cgroup/cgroup_test.go +++ b/cgroup/cgroup_test.go @@ -1,6 +1,7 @@ package cgroup import ( + "os" "path" "testing" @@ -236,3 +237,17 @@ func TestContainerByCgroup(t *testing.T) { as.Equal("ba7b10d15d16e10e3de7a2dcd408a3d971169ae303f46cfad4c5453c6326fee2", id) as.Nil(err) } + +// The registry relies on a process in systemd's /init.scope, or in the root +// cgroup, having an empty Id: it is not cached as ignored, so its exec after +// systemd moves it to a unit's cgroup is seen. +func TestInitScopeAndRootHaveEmptyId(t *testing.T) { + for _, content := range []string{"0::/init.scope\n", "0::/\n"} { + f := path.Join(t.TempDir(), "cgroup") + require.NoError(t, os.WriteFile(f, []byte(content), 0644)) + cg, err := NewFromProcessCgroupFile(f) + require.NoError(t, err) + assert.Equal(t, "", cg.Id, content) + assert.Equal(t, ContainerTypeStandaloneProcess, cg.ContainerType, content) + } +} diff --git a/containers/registry.go b/containers/registry.go index a873797a..96e85255 100644 --- a/containers/registry.go +++ b/containers/registry.go @@ -640,7 +640,12 @@ func (r *Registry) getOrCreateContainer(pid uint32) *Container { } id := calcId(cg, md) if id == "" { - if cg.Id == "/init.scope" && pid != 1 { + // systemd forks a unit's process inside its own /init.scope and + // moves it to the unit's cgroup before exec. Caching the pid as + // ignored here would drop that exec, and a unit that does nothing + // else would never be detected. /init.scope and the root cgroup + // both parse to an empty Id (cgroup.go skips them). + if cg.Id == "" && pid != 1 { klog.V(5).InfoS("ignoring without persisting", "cg", cg.Id, "pid", pid) } else { klog.V(5).InfoS("ignoring", "cg", cg.Id, "pid", pid)