From 9e787db1b108941edab18209a7468e6c555002ce Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Tue, 24 Mar 2015 20:41:17 -0400 Subject: [PATCH] cgroups: systemd: attempt to stop test scope, if any As reported in #477 the test scope may not be cleaned up between runs. In order to fix this we must be polite and remove the scope after we have done our test and attempt to remove an existing scope if it exists. This way we can guarantee our test will run. Signed-off-by: Brandon Philips --- cgroups/systemd/apply_systemd.go | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/cgroups/systemd/apply_systemd.go b/cgroups/systemd/apply_systemd.go index f3536406..85ee5db0 100644 --- a/cgroups/systemd/apply_systemd.go +++ b/cgroups/systemd/apply_systemd.go @@ -43,6 +43,10 @@ var subsystems = map[string]subsystem{ "freezer": &fs.FreezerGroup{}, } +const ( + testScopeWait = 4 +) + var ( connLock sync.Mutex theConn *systemd.Conn @@ -86,16 +90,41 @@ func UseSystemd() bool { } } + // Ensure the scope name we use doesn't exist. Use the Pid to + // avoid collisions between multiple libcontainer users on a + // single host. + scope := fmt.Sprintf("libcontainer-%d-systemd-test-default-dependencies.scope", os.Getpid()) + testScopeExists := true + for i := 0; i <= testScopeWait; i++ { + if _, err := theConn.StopUnit(scope, "replace"); err != nil { + if dbusError, ok := err.(dbus.Error); ok { + if strings.Contains(dbusError.Name, "org.freedesktop.systemd1.NoSuchUnit") { + testScopeExists = false + break + } + } + } + time.Sleep(time.Millisecond) + } + + // Bail out if we can't kill this scope without testing for DefaultDependencies + if testScopeExists { + return hasStartTransientUnit + } + // Assume StartTransientUnit on a scope allows DefaultDependencies hasTransientDefaultDependencies = true ddf := newProp("DefaultDependencies", false) - if _, err := theConn.StartTransientUnit("docker-systemd-test-default-dependencies.scope", "replace", ddf); err != nil { + if _, err := theConn.StartTransientUnit(scope, "replace", ddf); err != nil { if dbusError, ok := err.(dbus.Error); ok { if strings.Contains(dbusError.Name, "org.freedesktop.DBus.Error.PropertyReadOnly") { hasTransientDefaultDependencies = false } } } + + // Not critical because of the stop unit logic above. + theConn.StopUnit(scope, "replace") } return hasStartTransientUnit }