libcontainer: use errors.Is() and errors.As()
Make use of errors.Is() and errors.As() where appropriate to check the underlying error. The biggest motivation is to simplify the code. The feature requires go 1.13 but since merging #2256 we are already not supporting go 1.12 (which is an unsupported release anyway). Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
parent
c39f87a47a
commit
b2272b2cba
|
@ -8,6 +8,7 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer/cgroups"
|
||||
"github.com/opencontainers/runc/libcontainer/configs"
|
||||
|
@ -110,22 +111,18 @@ func isIgnorableError(rootless bool, err error) bool {
|
|||
if !rootless {
|
||||
return false
|
||||
}
|
||||
// TODO: rm errors.Cause once we switch to %w everywhere
|
||||
err = errors.Cause(err)
|
||||
// Is it an ordinary EPERM?
|
||||
if os.IsPermission(errors.Cause(err)) {
|
||||
if errors.Is(err, os.ErrPermission) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Try to handle other errnos.
|
||||
var errno error
|
||||
switch err := errors.Cause(err).(type) {
|
||||
case *os.PathError:
|
||||
errno = err.Err
|
||||
case *os.LinkError:
|
||||
errno = err.Err
|
||||
case *os.SyscallError:
|
||||
errno = err.Err
|
||||
// Handle some specific syscall errors.
|
||||
var errno syscall.Errno
|
||||
if errors.As(err, &errno) {
|
||||
return errno == unix.EROFS || errno == unix.EPERM || errno == unix.EACCES
|
||||
}
|
||||
return errno == unix.EROFS || errno == unix.EPERM || errno == unix.EACCES
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *Manager) getSubsystems() subsystemSet {
|
||||
|
|
|
@ -6,10 +6,8 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"syscall" // for Errno type only
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer/cgroups"
|
||||
"golang.org/x/sys/unix"
|
||||
|
@ -49,12 +47,8 @@ func setKernelMemory(path string, kernelMemoryLimit int64) error {
|
|||
// The EBUSY signal is returned on attempts to write to the
|
||||
// memory.kmem.limit_in_bytes file if the cgroup has children or
|
||||
// once tasks have been attached to the cgroup
|
||||
if pathErr, ok := err.(*os.PathError); ok {
|
||||
if errNo, ok := pathErr.Err.(syscall.Errno); ok {
|
||||
if errNo == unix.EBUSY {
|
||||
return fmt.Errorf("failed to set %s, because either tasks have already joined this cgroup or it has children", cgroupKernelMemoryLimit)
|
||||
}
|
||||
}
|
||||
if errors.Is(err, unix.EBUSY) {
|
||||
return fmt.Errorf("failed to set %s, because either tasks have already joined this cgroup or it has children", cgroupKernelMemoryLimit)
|
||||
}
|
||||
return fmt.Errorf("failed to write %v to %v: %v", kernelMemoryLimit, cgroupKernelMemoryLimit, err)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ package fs2
|
|||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
|
@ -25,20 +24,11 @@ func setPids(dirPath string, cgroup *configs.Cgroup) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func isNOTSUP(err error) bool {
|
||||
switch err := err.(type) {
|
||||
case *os.PathError:
|
||||
return err.Err == unix.ENOTSUP
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func statPidsWithoutController(dirPath string, stats *cgroups.Stats) error {
|
||||
// if the controller is not enabled, let's read PIDS from cgroups.procs
|
||||
// (or threads if cgroup.threads is enabled)
|
||||
contents, err := ioutil.ReadFile(filepath.Join(dirPath, "cgroup.procs"))
|
||||
if err != nil && isNOTSUP(err) {
|
||||
if errors.Is(err, unix.ENOTSUP) {
|
||||
contents, err = ioutil.ReadFile(filepath.Join(dirPath, "cgroup.threads"))
|
||||
}
|
||||
if err != nil {
|
||||
|
|
|
@ -576,7 +576,7 @@ func WriteCgroupProc(dir string, pid int) error {
|
|||
|
||||
// EINVAL might mean that the task being added to cgroup.procs is in state
|
||||
// TASK_NEW. We should attempt to do so again.
|
||||
if isEINVAL(err) {
|
||||
if errors.Is(err, unix.EINVAL) {
|
||||
time.Sleep(30 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
|
@ -586,15 +586,6 @@ func WriteCgroupProc(dir string, pid int) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func isEINVAL(err error) bool {
|
||||
switch err := err.(type) {
|
||||
case *os.PathError:
|
||||
return err.Err == unix.EINVAL
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Since the OCI spec is designed for cgroup v1, in some cases
|
||||
// there is need to convert from the cgroup v1 configuration to cgroup v2
|
||||
// the formula for BlkIOWeight is y = (1 + (x - 10) * 9999 / 990)
|
||||
|
|
|
@ -1855,10 +1855,7 @@ func (c *linuxContainer) isPaused() (bool, error) {
|
|||
data, err := ioutil.ReadFile(filepath.Join(fcg, filename))
|
||||
if err != nil {
|
||||
// If freezer cgroup is not mounted, the container would just be not paused.
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
if pathError, isPathError := err.(*os.PathError); isPathError && pathError.Err == syscall.ENODEV {
|
||||
if os.IsNotExist(err) || errors.Is(err, syscall.ENODEV) {
|
||||
return false, nil
|
||||
}
|
||||
return false, newSystemErrorWithCause(err, "checking if container is paused")
|
||||
|
|
Loading…
Reference in New Issue