Skip to content

Commit

Permalink
cgroup: refine the handling of error 'no cpu controller detected' (#5999
Browse files Browse the repository at this point in the history
)

ref #5953

Signed-off-by: Sen Han <00hnes@gmail.com>

Co-authored-by: lhy1024 <admin@liudos.us>
  • Loading branch information
hnes and lhy1024 authored Feb 16, 2023
1 parent c499e01 commit f99da66
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 5 deletions.
4 changes: 3 additions & 1 deletion pkg/cgroup/cgroup_cpu.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
"github.com/pingcap/errors"
)

var errNoCPUControllerDetected = errors.New("no cpu controller detected")

// Helper function for getCgroupCPU. Root is always "/", except in tests.
func getCgroupCPUHelper(root string) (CPUUsage, error) {
path, err := detectControlPath(filepath.Join(root, procPathCGroup), "cpu,cpuacct")
Expand All @@ -30,7 +32,7 @@ func getCgroupCPUHelper(root string) (CPUUsage, error) {

// No CPU controller detected
if path == "" {
return CPUUsage{}, errors.New("no cpu controller detected")
return CPUUsage{}, errNoCPUControllerDetected
}

mount, ver, err := getCgroupDetails(filepath.Join(root, procPathMountInfo), path, "cpu,cpuacct")
Expand Down
56 changes: 52 additions & 4 deletions pkg/cgroup/cgroup_cpu_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,57 @@
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build linux && enable_flaky_tests
//go:build linux

package cgroup

import (
"fmt"
"regexp"
"runtime"
"strconv"
"sync"
"syscall"
"testing"

"github.com/stretchr/testify/require"
)

func checkKernelVersionNewerThan(t *testing.T, major, minor int) bool {
u := syscall.Utsname{}
err := syscall.Uname(&u)
require.NoError(t, err)
releaseBs := make([]byte, 0, len(u.Release))
for _, v := range u.Release {
if v == 0 {
break
}
releaseBs = append(releaseBs, byte(v))
}
releaseStr := string(releaseBs)
t.Log("kernel release string:", releaseStr)
versionInfoRE := regexp.MustCompile(`[0-9]+\.[0-9]+\.[0-9]+`)
kernelVerion := versionInfoRE.FindAllString(releaseStr, 1)
require.Equal(t, 1, len(kernelVerion), fmt.Sprintf("release str is %s", releaseStr))
kernelVersionPartRE := regexp.MustCompile(`[0-9]+`)
kernelVersionParts := kernelVersionPartRE.FindAllString(kernelVerion[0], -1)
require.Equal(t, 3, len(kernelVersionParts), fmt.Sprintf("kernel verion str is %s", kernelVerion[0]))
t.Logf("parsed kernel version parts: major %s, minor %s, patch %s",
kernelVersionParts[0], kernelVersionParts[1], kernelVersionParts[2])
mustConvInt := func(s string) int {
i, err := strconv.Atoi(s)
require.NoError(t, err, s)
return i
}
versionNewerThanFlag := false
if mustConvInt(kernelVersionParts[0]) > major {
versionNewerThanFlag = true
} else if mustConvInt(kernelVersionParts[0]) == major && mustConvInt(kernelVersionParts[1]) > minor {
versionNewerThanFlag = true
}
return versionNewerThanFlag
}

func TestGetCgroupCPU(t *testing.T) {
exit := make(chan struct{})
var wg sync.WaitGroup
Expand All @@ -42,9 +81,18 @@ func TestGetCgroupCPU(t *testing.T) {
}()
}
cpu, err := GetCgroupCPU()
require.NoError(t, err)
require.NotZero(t, cpu.Period)
require.Less(t, int64(1), cpu.Period)
if err == errNoCPUControllerDetected {
// for more information, please refer https://github.com/pingcap/tidb/pull/41347
if checkKernelVersionNewerThan(t, 4, 7) {
require.NoError(t, err, "linux version > v4.7 and err still happens")
} else {
t.Logf("the error '%s' is ignored because the kernel is too old", err)
}
} else {
require.NoError(t, err)
require.NotZero(t, cpu.Period)
require.Less(t, int64(1), cpu.Period)
}
close(exit)
wg.Wait()
}

0 comments on commit f99da66

Please sign in to comment.