diff --git a/libcontainer/cgroups/systemd/apply_systemd.go b/libcontainer/cgroups/systemd/apply_systemd.go index 3c1543e81..ac65d43ad 100644 --- a/libcontainer/cgroups/systemd/apply_systemd.go +++ b/libcontainer/cgroups/systemd/apply_systemd.go @@ -75,7 +75,8 @@ var ( hasStartTransientUnit bool hasStartTransientSliceUnit bool hasTransientDefaultDependencies bool - hasDelegate bool + hasDelegateScope bool + hasDelegateSlice bool ) func newProp(name string, units interface{}) systemdDbus.Property { @@ -150,12 +151,12 @@ func UseSystemd() bool { theConn.StopUnit(scope, "replace", nil) // Assume StartTransientUnit on a scope allows Delegate - hasDelegate = true - dl := newProp("Delegate", true) - if _, err := theConn.StartTransientUnit(scope, "replace", []systemdDbus.Property{dl}, nil); err != nil { + hasDelegateScope = true + dlScope := newProp("Delegate", true) + if _, err := theConn.StartTransientUnit(scope, "replace", []systemdDbus.Property{dlScope}, nil); err != nil { if dbusError, ok := err.(dbus.Error); ok { if strings.Contains(dbusError.Name, "org.freedesktop.DBus.Error.PropertyReadOnly") { - hasDelegate = false + hasDelegateScope = false } } } @@ -187,6 +188,22 @@ func UseSystemd() bool { time.Sleep(time.Millisecond) } + // Not critical because of the stop unit logic above. + theConn.StopUnit(slice, "replace", nil) + + // Assume StartTransientUnit on a slice allows Delegate + hasDelegateSlice = true + dlSlice := newProp("Delegate", true) + if _, err := theConn.StartTransientUnit(slice, "replace", []systemdDbus.Property{dlSlice}, nil); err != nil { + if dbusError, ok := err.(dbus.Error); ok { + // Starting with systemd v237, Delegate is not even a property of slices anymore, + // so the D-Bus call fails with "InvalidArgs" error. + if strings.Contains(dbusError.Name, "org.freedesktop.DBus.Error.PropertyReadOnly") || strings.Contains(dbusError.Name, "org.freedesktop.DBus.Error.InvalidArgs") { + hasDelegateSlice = false + } + } + } + // Not critical because of the stop unit logic above. theConn.StopUnit(scope, "replace", nil) theConn.StopUnit(slice, "replace", nil) @@ -242,9 +259,16 @@ func (m *Manager) Apply(pid int) error { properties = append(properties, newProp("PIDs", []uint32{uint32(pid)})) } - if hasDelegate { - // This is only supported on systemd versions 218 and above. - properties = append(properties, newProp("Delegate", true)) + // Check if we can delegate. This is only supported on systemd versions 218 and above. + if strings.HasSuffix(unitName, ".slice") { + if hasDelegateSlice { + // systemd 237 and above no longer allows delegation on a slice + properties = append(properties, newProp("Delegate", true)) + } + } else { + if hasDelegateScope { + properties = append(properties, newProp("Delegate", true)) + } } // Always enable accounting, this gets us the same behaviour as the fs implementation,