diff --git a/libcontainer/cgroups/fs/freezer.go b/libcontainer/cgroups/fs/freezer.go index 11cb1646f48..79453969884 100644 --- a/libcontainer/cgroups/fs/freezer.go +++ b/libcontainer/cgroups/fs/freezer.go @@ -15,6 +15,8 @@ import ( "golang.org/x/sys/unix" ) +var FreezerTimeout = errors.New("freezer timeout") + type FreezerGroup struct { } @@ -29,6 +31,7 @@ func (s *FreezerGroup) Apply(path string, d *cgroupData) error { func (s *FreezerGroup) Set(path string, cgroup *configs.Cgroup) error { switch cgroup.Resources.Freezer { case configs.Frozen, configs.Thawed: + maxRetry := 2 for { // In case this loop does not exit because it doesn't get the expected // state, let's write again this state, hoping it's going to be properly @@ -38,14 +41,31 @@ func (s *FreezerGroup) Set(path string, cgroup *configs.Cgroup) error { return err } - state, err := s.GetState(path) - if err != nil { - return err - } - if state == cgroup.Resources.Freezer { - break + var state configs.FreezerState + var e error + c := make(chan bool, 1) + + go func() { + state, e = s.GetState(path) + c <- true + }() + + select { + case <-c: + if e != nil { + return e + } + if state == cgroup.Resources.Freezer { + return nil + } + + case <-time.After(1 * time.Millisecond): } + maxRetry = maxRetry - 1 + if maxRetry <= 0 { + return FreezerTimeout + } time.Sleep(1 * time.Millisecond) } case configs.Undefined: @@ -54,7 +74,6 @@ func (s *FreezerGroup) Set(path string, cgroup *configs.Cgroup) error { return fmt.Errorf("Invalid argument '%s' to freezer.state", string(cgroup.Resources.Freezer)) } - return nil } func (s *FreezerGroup) GetStats(path string, stats *cgroups.Stats) error { diff --git a/libcontainer/cgroups/systemd/v1.go b/libcontainer/cgroups/systemd/v1.go index 64af1d94b3e..f867db69895 100644 --- a/libcontainer/cgroups/systemd/v1.go +++ b/libcontainer/cgroups/systemd/v1.go @@ -8,6 +8,7 @@ import ( "path/filepath" "strings" "sync" + "time" systemdDbus "github.com/coreos/go-systemd/v22/dbus" "github.com/opencontainers/runc/libcontainer/cgroups" @@ -307,6 +308,18 @@ func (m *legacyManager) Freeze(state configs.FreezerState) error { freezer := &fs.FreezerGroup{} if err := freezer.Set(path, m.cgroups); err != nil { m.cgroups.Resources.Freezer = prevState + if err == fs.FreezerTimeout { + if err := freezer.Set(path, m.cgroups); err != nil { + return err + } + + time.Sleep(1 * time.Millisecond) + m.cgroups.Resources.Freezer = state + if err := freezer.Set(path, m.cgroups); err != nil { + m.cgroups.Resources.Freezer = prevState + return err + } + } return err } return nil