Skip to content

Commit bdf3524

Browse files
author
Tom Godkin
committed
Retry adding pids to cgroups when EINVAL occurs
The kernel will sometimes return EINVAL when writing a pid to a cgroup.procs file. It does so when the task being added still has the state TASK_NEW. See: https://elixir.bootlin.com/linux/v4.8/source/kernel/sched/core.c#L8286 Co-authored-by: Danail Branekov <[email protected]> Signed-off-by: Tom Godkin <[email protected]> Signed-off-by: Danail Branekov <[email protected]>
1 parent f5b9991 commit bdf3524

File tree

1 file changed

+35
-5
lines changed

1 file changed

+35
-5
lines changed

libcontainer/cgroups/utils.go

+35-5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"time"
1515

1616
units "github.com/docker/go-units"
17+
"golang.org/x/sys/unix"
1718
)
1819

1920
const (
@@ -463,11 +464,40 @@ func WriteCgroupProc(dir string, pid int) error {
463464
return fmt.Errorf("no such directory for %s", CgroupProcesses)
464465
}
465466

466-
// Don't attach any pid to the cgroup if -1 is specified as a pid
467-
if pid != -1 {
468-
if err := ioutil.WriteFile(filepath.Join(dir, CgroupProcesses), []byte(strconv.Itoa(pid)), 0700); err != nil {
469-
return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err)
467+
// Dont attach any pid to the cgroup if -1 is specified as a pid
468+
if pid == -1 {
469+
return nil
470+
}
471+
472+
cgroupProcessesFile, err := os.OpenFile(filepath.Join(dir, CgroupProcesses), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0700)
473+
if err != nil {
474+
return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err)
475+
}
476+
defer cgroupProcessesFile.Close()
477+
478+
for i := 0; i < 5; i++ {
479+
_, err = cgroupProcessesFile.WriteString(strconv.Itoa(pid))
480+
if err == nil {
481+
return nil
470482
}
483+
484+
// EINVAL might mean that the task being added to cgroup.procs is in state
485+
// TASK_NEW. We should attempt to do so again.
486+
if isEINVAL(err) {
487+
time.Sleep(30 * time.Millisecond)
488+
continue
489+
}
490+
491+
return fmt.Errorf("failed to write %v to %v: %v", pid, CgroupProcesses, err)
492+
}
493+
return err
494+
}
495+
496+
func isEINVAL(err error) bool {
497+
switch err := err.(type) {
498+
case *os.PathError:
499+
return err.Err == unix.EINVAL
500+
default:
501+
return false
471502
}
472-
return nil
473503
}

0 commit comments

Comments
 (0)