Detect whether Delegate is available on both slices and scopes
Starting with systemd 237, in preparation for cgroup v2, delegation is
only now available for scopes, not slices.
Update libcontainer code to detect whether delegation is available on
both and use that information when creating new slices.
@@ -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,10 +259,17 @@ 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.
+ // 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,
// plus the kernel has some problems with joining the memory cgroup at a later time.
