@@ -32,6 +32,11 @@ const (
3232 defaultSlice = "system.slice"
3333)
3434
35+ var (
36+ canDelegate bool
37+ once sync.Once
38+ )
39+
3540func Systemd () ([]Subsystem , error ) {
3641 root , err := v1MountPoint ()
3742 if err != nil {
@@ -80,15 +85,39 @@ func (s *SystemdController) Create(path string, resources *specs.LinuxResources)
8085 }
8186 defer conn .Close ()
8287 slice , name := splitName (path )
88+ // We need to see if systemd can handle the delegate property
89+ // Systemd will return an error if it cannot handle delegate regardless
90+ // of its bool setting.
91+ checkDelegate := func () {
92+ canDelegate = true
93+ dlSlice := newProperty ("Delegate" , true )
94+ if _ , err := conn .StartTransientUnit (slice , "testdelegate" , []systemdDbus.Property {dlSlice }, nil ); err != nil {
95+ if dbusError , ok := err .(dbus.Error ); ok {
96+ // Starting with systemd v237, Delegate is not even a property of slices anymore,
97+ // so the D-Bus call fails with "InvalidArgs" error.
98+ if strings .Contains (dbusError .Name , "org.freedesktop.DBus.Error.PropertyReadOnly" ) || strings .Contains (dbusError .Name , "org.freedesktop.DBus.Error.InvalidArgs" ) {
99+ canDelegate = false
100+ }
101+ }
102+ }
103+
104+ conn .StopUnit (slice , "testDelegate" , nil )
105+ }
106+ once .Do (checkDelegate )
83107 properties := []systemdDbus.Property {
84108 systemdDbus .PropDescription (fmt .Sprintf ("cgroup %s" , name )),
85109 systemdDbus .PropWants (slice ),
86110 newProperty ("DefaultDependencies" , false ),
87- newProperty ("Delegate" , true ),
88111 newProperty ("MemoryAccounting" , true ),
89112 newProperty ("CPUAccounting" , true ),
90113 newProperty ("BlockIOAccounting" , true ),
91114 }
115+
116+ // If we can delegate, we add the property back in
117+ if canDelegate {
118+ properties = append (properties , newProperty ("Delegate" , true ))
119+ }
120+
92121 ch := make (chan string )
93122 _ , err = conn .StartTransientUnit (name , "replace" , properties , ch )
94123 if err != nil {
0 commit comments