diff --git a/libcontainer/init_linux.go b/libcontainer/init_linux.go index e24d81817c1..6b59a87b5d2 100644 --- a/libcontainer/init_linux.go +++ b/libcontainer/init_linux.go @@ -76,10 +76,23 @@ type initConfig struct { // Init is part of "runc init" implementation. func Init() { + var cpus0, cpus1 unix.CPUSet + err := unix.SchedGetaffinity(0, &cpus0) + if err != nil { + fmt.Fprintf(os.Stderr, "sched_getaffinity 0 error: %s\n", err) + os.Exit(255) + } + runtime.GOMAXPROCS(1) runtime.LockOSThread() - if err := startInitialization(); err != nil { + err = unix.SchedGetaffinity(0, &cpus1) + if err != nil { + fmt.Fprintf(os.Stderr, "sched_getaffinity 0 error: %s\n", err) + os.Exit(255) + } + + if err := startInitialization(&cpus0, &cpus1); err != nil { // If the error is returned, it was not communicated // back to the parent (which is not a common case), // so print it to stderr here as a last resort. @@ -97,7 +110,7 @@ func Init() { // Normally, this function does not return. If it returns, with or without an // error, it means the initialization has failed. If the error is returned, // it means the error can not be communicated back to the parent. -func startInitialization() (retErr error) { +func startInitialization(cpus0, cpus1 *unix.CPUSet) (retErr error) { // Get the synchronisation pipe. envSyncPipe := os.Getenv("_LIBCONTAINER_SYNCPIPE") syncPipeFd, err := strconv.Atoi(envSyncPipe) @@ -155,18 +168,19 @@ func startInitialization() (retErr error) { // See tests/integration/cpu_affinity.bats. if logrus.GetLevel() >= logrus.DebugLevel { - var cpus unix.CPUSet - err := unix.SchedGetaffinity(0, &cpus) + var cpus2 unix.CPUSet + err := unix.SchedGetaffinity(0, &cpus2) if err != nil { logrus.Debugf("sched_getaffinity: error %v", err) - } else { + } + for n, cpus := range []*unix.CPUSet{cpus0, cpus1, &cpus2} { var list []int for i := 0; i < 32; i++ { if cpus.IsSet(i) { list = append(list, i) } } - logrus.Debugf("Initial CPUs: %v", list) + logrus.Debugf("Initial CPUs %d: %v", n, list) } } diff --git a/tests/integration/cpu_affinity.bats b/tests/integration/cpu_affinity.bats index 8a823ce23cc..cac23f9a80d 100644 --- a/tests/integration/cpu_affinity.bats +++ b/tests/integration/cpu_affinity.bats @@ -28,14 +28,14 @@ function first_cpu() { runc run -d --console-socket "$CONSOLE_SOCKET" ct1 [ "$status" -eq 0 ] - for cpus in "$first" "$first-$second" "$first,$second" "$second"; do + for cpus in "$second" "$first-$second" "$first,$second" "$first"; do proc=' { "terminal": false, "execCPUAffinity": { "initial": "'$cpus'" }, - "args": [ "/bin/true" ], + "args": [ "/bin/grep", "Cpus_allowed_list:", "/proc/self/status" ], "cwd": "/" }' exp=${cpus//,/-} # 1. "," --> "-". @@ -47,27 +47,31 @@ function first_cpu() { [[ "$output" == *"nsexec-1["*": CPUs: $exp "* ]] [[ "$output" == *"nsexec-2["*": CPUs: $exp "* ]] [[ "$output" == *"Initial CPU affinity: $cpus"* ]] - [[ "$output" == *"Initial CPUs: [$exp]"* ]] + [[ "$output" == *"Initial CPUs 0: [$exp]"* ]] + [[ "$output" == *"Initial CPUs 1: [$exp]"* ]] + [[ "$output" == *"Initial CPUs 2: [$exp]"* ]] done } @test "runc exec [CPU affinity, initial and final are set]" { - first="$(first_cpu)" - second=$((first + 1)) # Hacky; might not work in all environments. + initial="$(first_cpu)" + final=$((initial + 1)) # Hacky; might not work in all environments. - update_config " .process.execCPUAffinity.initial = \"$first\" - | .process.execCPUAffinity.final = \"$second\"" + update_config " .process.execCPUAffinity.initial = \"$initial\" + | .process.execCPUAffinity.final = \"$final\"" runc run -d --console-socket "$CONSOLE_SOCKET" ct1 [ "$status" -eq 0 ] runc --debug exec ct1 grep "Cpus_allowed_list:" /proc/self/status [ "$status" -eq 0 ] - [[ "$output" == *"nsexec["*": CPUs: $first "* ]] - [[ "$output" == *"nsexec-0["*": CPUs: $first "* ]] - [[ "$output" == *"nsexec-1["*": CPUs: $first "* ]] - [[ "$output" == *"nsexec-2["*": CPUs: $first "* ]] - [[ "$output" == *"Initial CPU affinity: $first"* ]] - [[ "$output" == *"Initial CPUs: [$first]"* ]] - [[ "$output" == *"Cpus_allowed_list: $second"* ]] # Mind the literal tab. + [[ "$output" == *"nsexec["*": CPUs: $initial "* ]] + [[ "$output" == *"nsexec-0["*": CPUs: $initial "* ]] + [[ "$output" == *"nsexec-1["*": CPUs: $initial "* ]] + [[ "$output" == *"nsexec-2["*": CPUs: $initial "* ]] + [[ "$output" == *"Initial CPU affinity: $initial"* ]] + [[ "$output" == *"Initial CPUs 0: [$initial]"* ]] + [[ "$output" == *"Initial CPUs 1: [$initial]"* ]] + [[ "$output" == *"Initial CPUs 2: [$initial]"* ]] + [[ "$output" == *"Cpus_allowed_list: $final"* ]] # Mind the literal tab. }