mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Port shim fix (#27)
Port shim fixes containerd/containerd#3264, containerd/containerd#3264 Update containerd to newest release/1.2 commit.
This commit is contained in:
@@ -21,6 +21,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/containerd/console"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/runtime/proc"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@@ -38,10 +39,12 @@ func (s *deletedState) Start(ctx context.Context) error {
|
||||
|
||||
func (s *deletedState) Delete(ctx context.Context) error {
|
||||
return errors.Errorf("cannot delete a deleted process")
|
||||
return errors.Wrap(errdefs.ErrNotFound, "cannot delete a deleted process")
|
||||
}
|
||||
|
||||
func (s *deletedState) Kill(ctx context.Context, sig uint32, all bool) error {
|
||||
return errors.Errorf("cannot kill a deleted process")
|
||||
return errors.Wrap(errdefs.ErrNotFound, "cannot kill a deleted process")
|
||||
}
|
||||
|
||||
func (s *deletedState) SetExited(status int) {
|
||||
|
||||
+27
-4
@@ -23,8 +23,10 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
|
||||
"github.com/containerd/containerd/log"
|
||||
"github.com/containerd/fifo"
|
||||
runc "github.com/containerd/go-runc"
|
||||
)
|
||||
@@ -39,7 +41,7 @@ var bufPool = sync.Pool{
|
||||
}
|
||||
|
||||
func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, wg, cwg *sync.WaitGroup) error {
|
||||
var sameFile io.WriteCloser
|
||||
var sameFile *countingWriteCloser
|
||||
for _, i := range []struct {
|
||||
name string
|
||||
dest func(wc io.WriteCloser, rc io.Closer)
|
||||
@@ -53,7 +55,9 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w
|
||||
cwg.Done()
|
||||
p := bufPool.Get().(*[]byte)
|
||||
defer bufPool.Put(p)
|
||||
io.CopyBuffer(wc, rio.Stdout(), *p)
|
||||
if _, err := io.CopyBuffer(wc, rio.Stdout(), *p); err != nil {
|
||||
log.G(ctx).Warn("error copying stdout")
|
||||
}
|
||||
wg.Done()
|
||||
wc.Close()
|
||||
if rc != nil {
|
||||
@@ -70,7 +74,9 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w
|
||||
cwg.Done()
|
||||
p := bufPool.Get().(*[]byte)
|
||||
defer bufPool.Put(p)
|
||||
io.CopyBuffer(wc, rio.Stderr(), *p)
|
||||
if _, err := io.CopyBuffer(wc, rio.Stderr(), *p); err != nil {
|
||||
log.G(ctx).Warn("error copying stderr")
|
||||
}
|
||||
wg.Done()
|
||||
wc.Close()
|
||||
if rc != nil {
|
||||
@@ -97,6 +103,7 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w
|
||||
}
|
||||
} else {
|
||||
if sameFile != nil {
|
||||
sameFile.count++
|
||||
i.dest(sameFile, nil)
|
||||
continue
|
||||
}
|
||||
@@ -104,7 +111,10 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w
|
||||
return fmt.Errorf("gvisor-containerd-shim: opening %s failed: %s", i.name, err)
|
||||
}
|
||||
if stdout == stderr {
|
||||
sameFile = fw
|
||||
sameFile = &countingWriteCloser{
|
||||
WriteCloser: fw,
|
||||
count: 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
i.dest(fw, fr)
|
||||
@@ -129,6 +139,19 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w
|
||||
return nil
|
||||
}
|
||||
|
||||
// countingWriteCloser masks io.Closer() until close has been invoked a certain number of times.
|
||||
type countingWriteCloser struct {
|
||||
io.WriteCloser
|
||||
count int64
|
||||
}
|
||||
|
||||
func (c *countingWriteCloser) Close() error {
|
||||
if atomic.AddInt64(&c.count, -1) > 0 {
|
||||
return nil
|
||||
}
|
||||
return c.WriteCloser.Close()
|
||||
}
|
||||
|
||||
// isFifo checks if a file is a fifo
|
||||
// if the file does not exist then it returns false
|
||||
func isFifo(path string) (bool, error) {
|
||||
|
||||
+5
-5
@@ -1,11 +1,11 @@
|
||||
github.com/BurntSushi/toml v0.3.0
|
||||
github.com/containerd/cgroups 5e610833b72089b37d0e615de9a92dfc043757c2
|
||||
github.com/containerd/cgroups 4994991857f9b0ae8dc439551e8bebdbb4bf66c1
|
||||
github.com/containerd/console c12b1e7919c14469339a5d38f2f8ed9b64a9de23
|
||||
github.com/containerd/containerd v1.2.2
|
||||
github.com/containerd/containerd d0319ec44af6ff59f3d6d38ae463d2a68b8ad12a # release/1.2
|
||||
github.com/containerd/cri 8a0bd84b9a4c988a3098fca8fedcb9c0f14d9d08
|
||||
github.com/containerd/fifo 3d5202aec260678c48179c56f40e6f38a095738c
|
||||
github.com/containerd/go-runc 5a6d9f37cfa36b15efba46dc7ea349fa9b7143c3
|
||||
github.com/containerd/ttrpc 2a805f71863501300ae1976d29f0454ae003e85a
|
||||
github.com/containerd/ttrpc 699c4e40d1e7416e08bf7019c7ce2e9beced4636
|
||||
github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
|
||||
github.com/coreos/go-systemd 48702e0da86bd25e76cfef347e2adeb434a0d0a6
|
||||
github.com/docker/go-units v0.3.1
|
||||
@@ -13,12 +13,12 @@ github.com/godbus/dbus c7fdd8b5cd55e87b4e1f4e372cdb1db61dd6c66f
|
||||
github.com/gogo/protobuf v1.0.0
|
||||
github.com/golang/protobuf v1.1.0
|
||||
github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7
|
||||
github.com/opencontainers/runc 96ec2177ae841256168fcf76954f7177af9446eb
|
||||
github.com/opencontainers/runc v1.0.0-rc8
|
||||
github.com/opencontainers/runtime-spec eba862dc2470385a233c7507392675cbeadf7353
|
||||
github.com/pkg/errors v0.8.0
|
||||
github.com/sirupsen/logrus v1.0.0
|
||||
golang.org/x/crypto 49796115aa4b964c318aad4f3084fdb41e9aa067
|
||||
golang.org/x/net b3756b4b77d7b13260a0a2ec658753cf48922eac
|
||||
golang.org/x/sys 1b2967e3c290b7c545b3db0deeda16e9be4f98a2 https://github.com/golang/sys
|
||||
golang.org/x/sys 41f3e6584952bb034a481797859f6ab34b6803bd https://github.com/golang/sys
|
||||
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
|
||||
google.golang.org/grpc v1.12.0
|
||||
|
||||
+13
-1
@@ -1,8 +1,9 @@
|
||||
# cgroups
|
||||
|
||||
[](https://travis-ci.org/containerd/cgroups)
|
||||
|
||||
[](https://codecov.io/gh/containerd/cgroups)
|
||||
[](https://godoc.org/github.com/containerd/cgroups)
|
||||
[](https://goreportcard.com/report/github.com/containerd/cgroups)
|
||||
|
||||
Go package for creating, managing, inspecting, and destroying cgroups.
|
||||
The resources format for settings on the cgroup uses the OCI runtime-spec found
|
||||
@@ -110,3 +111,14 @@ err := control.MoveTo(destination)
|
||||
```go
|
||||
subCgroup, err := control.New("child", resources)
|
||||
```
|
||||
|
||||
## Project details
|
||||
|
||||
Cgroups is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE).
|
||||
As a containerd sub-project, you will find the:
|
||||
|
||||
* [Project governance](https://github.com/containerd/project/blob/master/GOVERNANCE.md),
|
||||
* [Maintainers](https://github.com/containerd/project/blob/master/MAINTAINERS),
|
||||
* and [Contributing guidelines](https://github.com/containerd/project/blob/master/CONTRIBUTING.md)
|
||||
|
||||
information in our [`containerd/project`](https://github.com/containerd/project) repository.
|
||||
|
||||
+34
-23
@@ -191,31 +191,42 @@ func (b *blkioController) readEntry(devices map[deviceKey]string, path, name str
|
||||
}
|
||||
|
||||
func createBlkioSettings(blkio *specs.LinuxBlockIO) []blkioSettings {
|
||||
settings := []blkioSettings{
|
||||
{
|
||||
name: "weight",
|
||||
value: blkio.Weight,
|
||||
format: uintf,
|
||||
},
|
||||
{
|
||||
name: "leaf_weight",
|
||||
value: blkio.LeafWeight,
|
||||
format: uintf,
|
||||
},
|
||||
}
|
||||
for _, wd := range blkio.WeightDevice {
|
||||
settings := []blkioSettings{}
|
||||
|
||||
if blkio.Weight != nil {
|
||||
settings = append(settings,
|
||||
blkioSettings{
|
||||
name: "weight_device",
|
||||
value: wd,
|
||||
format: weightdev,
|
||||
},
|
||||
blkioSettings{
|
||||
name: "leaf_weight_device",
|
||||
value: wd,
|
||||
format: weightleafdev,
|
||||
name: "weight",
|
||||
value: blkio.Weight,
|
||||
format: uintf,
|
||||
})
|
||||
}
|
||||
if blkio.LeafWeight != nil {
|
||||
settings = append(settings,
|
||||
blkioSettings{
|
||||
name: "leaf_weight",
|
||||
value: blkio.LeafWeight,
|
||||
format: uintf,
|
||||
})
|
||||
}
|
||||
for _, wd := range blkio.WeightDevice {
|
||||
if wd.Weight != nil {
|
||||
settings = append(settings,
|
||||
blkioSettings{
|
||||
name: "weight_device",
|
||||
value: wd,
|
||||
format: weightdev,
|
||||
})
|
||||
}
|
||||
if wd.LeafWeight != nil {
|
||||
settings = append(settings,
|
||||
blkioSettings{
|
||||
name: "leaf_weight_device",
|
||||
value: wd,
|
||||
format: weightleafdev,
|
||||
})
|
||||
}
|
||||
}
|
||||
for _, t := range []struct {
|
||||
name string
|
||||
list []specs.LinuxThrottleDevice
|
||||
@@ -265,12 +276,12 @@ func uintf(v interface{}) []byte {
|
||||
|
||||
func weightdev(v interface{}) []byte {
|
||||
wd := v.(specs.LinuxWeightDevice)
|
||||
return []byte(fmt.Sprintf("%d:%d %d", wd.Major, wd.Minor, wd.Weight))
|
||||
return []byte(fmt.Sprintf("%d:%d %d", wd.Major, wd.Minor, *wd.Weight))
|
||||
}
|
||||
|
||||
func weightleafdev(v interface{}) []byte {
|
||||
wd := v.(specs.LinuxWeightDevice)
|
||||
return []byte(fmt.Sprintf("%d:%d %d", wd.Major, wd.Minor, wd.LeafWeight))
|
||||
return []byte(fmt.Sprintf("%d:%d %d", wd.Major, wd.Minor, *wd.LeafWeight))
|
||||
}
|
||||
|
||||
func throttleddev(v interface{}) []byte {
|
||||
|
||||
+90
-6
@@ -30,47 +30,88 @@ import (
|
||||
)
|
||||
|
||||
// New returns a new control via the cgroup cgroups interface
|
||||
func New(hierarchy Hierarchy, path Path, resources *specs.LinuxResources) (Cgroup, error) {
|
||||
func New(hierarchy Hierarchy, path Path, resources *specs.LinuxResources, opts ...InitOpts) (Cgroup, error) {
|
||||
config := newInitConfig()
|
||||
for _, o := range opts {
|
||||
if err := o(config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
subsystems, err := hierarchy()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var active []Subsystem
|
||||
for _, s := range subsystems {
|
||||
// check if subsystem exists
|
||||
if err := initializeSubsystem(s, path, resources); err != nil {
|
||||
if err == ErrControllerNotActive {
|
||||
if config.InitCheck != nil {
|
||||
if skerr := config.InitCheck(s, path, err); skerr != nil {
|
||||
if skerr != ErrIgnoreSubsystem {
|
||||
return nil, skerr
|
||||
}
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
active = append(active, s)
|
||||
}
|
||||
return &cgroup{
|
||||
path: path,
|
||||
subsystems: subsystems,
|
||||
subsystems: active,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Load will load an existing cgroup and allow it to be controlled
|
||||
func Load(hierarchy Hierarchy, path Path) (Cgroup, error) {
|
||||
func Load(hierarchy Hierarchy, path Path, opts ...InitOpts) (Cgroup, error) {
|
||||
config := newInitConfig()
|
||||
for _, o := range opts {
|
||||
if err := o(config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
var activeSubsystems []Subsystem
|
||||
subsystems, err := hierarchy()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// check the the subsystems still exist
|
||||
// check that the subsystems still exist, and keep only those that actually exist
|
||||
for _, s := range pathers(subsystems) {
|
||||
p, err := path(s.Name())
|
||||
if err != nil {
|
||||
if os.IsNotExist(errors.Cause(err)) {
|
||||
return nil, ErrCgroupDeleted
|
||||
}
|
||||
if err == ErrControllerNotActive {
|
||||
if config.InitCheck != nil {
|
||||
if skerr := config.InitCheck(s, path, err); skerr != nil {
|
||||
if skerr != ErrIgnoreSubsystem {
|
||||
return nil, skerr
|
||||
}
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if _, err := os.Lstat(s.Path(p)); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, ErrCgroupDeleted
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
activeSubsystems = append(activeSubsystems, s)
|
||||
}
|
||||
// if we do not have any active systems then the cgroup is deleted
|
||||
if len(activeSubsystems) == 0 {
|
||||
return nil, ErrCgroupDeleted
|
||||
}
|
||||
return &cgroup{
|
||||
path: path,
|
||||
subsystems: subsystems,
|
||||
subsystems: activeSubsystems,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -319,6 +360,49 @@ func (c *cgroup) processes(subsystem Name, recursive bool) ([]Process, error) {
|
||||
return processes, err
|
||||
}
|
||||
|
||||
// Tasks returns the tasks running inside the cgroup along
|
||||
// with the subsystem used, pid, and path
|
||||
func (c *cgroup) Tasks(subsystem Name, recursive bool) ([]Task, error) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
if c.err != nil {
|
||||
return nil, c.err
|
||||
}
|
||||
return c.tasks(subsystem, recursive)
|
||||
}
|
||||
|
||||
func (c *cgroup) tasks(subsystem Name, recursive bool) ([]Task, error) {
|
||||
s := c.getSubsystem(subsystem)
|
||||
sp, err := c.path(subsystem)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
path := s.(pather).Path(sp)
|
||||
var tasks []Task
|
||||
err = filepath.Walk(path, func(p string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !recursive && info.IsDir() {
|
||||
if p == path {
|
||||
return nil
|
||||
}
|
||||
return filepath.SkipDir
|
||||
}
|
||||
dir, name := filepath.Split(p)
|
||||
if name != cgroupTasks {
|
||||
return nil
|
||||
}
|
||||
procs, err := readTasksPids(dir, subsystem)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tasks = append(tasks, procs...)
|
||||
return nil
|
||||
})
|
||||
return tasks, err
|
||||
}
|
||||
|
||||
// Freeze freezes the entire cgroup and all the processes inside it
|
||||
func (c *cgroup) Freeze() error {
|
||||
c.mu.Lock()
|
||||
|
||||
+11
@@ -44,6 +44,15 @@ type Process struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
type Task struct {
|
||||
// Subsystem is the name of the subsystem that the task is in
|
||||
Subsystem Name
|
||||
// Pid is the process id of the task
|
||||
Pid int
|
||||
// Path is the full path of the subsystem and location that the task is in
|
||||
Path string
|
||||
}
|
||||
|
||||
// Cgroup handles interactions with the individual groups to perform
|
||||
// actions on them as them main interface to this cgroup package
|
||||
type Cgroup interface {
|
||||
@@ -64,6 +73,8 @@ type Cgroup interface {
|
||||
Update(resources *specs.LinuxResources) error
|
||||
// Processes returns all the processes in a select subsystem for the cgroup
|
||||
Processes(Name, bool) ([]Process, error)
|
||||
// Tasks returns all the tasks in a select subsystem for the cgroup
|
||||
Tasks(Name, bool) ([]Task, error)
|
||||
// Freeze freezes or pauses all processes inside the cgroup
|
||||
Freeze() error
|
||||
// Thaw thaw or resumes all processes inside the cgroup
|
||||
|
||||
+5
-5
@@ -57,21 +57,21 @@ func (c *cpusetController) Create(path string, resources *specs.LinuxResources)
|
||||
if resources.CPU != nil {
|
||||
for _, t := range []struct {
|
||||
name string
|
||||
value *string
|
||||
value string
|
||||
}{
|
||||
{
|
||||
name: "cpus",
|
||||
value: &resources.CPU.Cpus,
|
||||
value: resources.CPU.Cpus,
|
||||
},
|
||||
{
|
||||
name: "mems",
|
||||
value: &resources.CPU.Mems,
|
||||
value: resources.CPU.Mems,
|
||||
},
|
||||
} {
|
||||
if t.value != nil {
|
||||
if t.value != "" {
|
||||
if err := ioutil.WriteFile(
|
||||
filepath.Join(c.Path(path), fmt.Sprintf("cpuset.%s", t.name)),
|
||||
[]byte(*t.value),
|
||||
[]byte(t.value),
|
||||
defaultFilePerm,
|
||||
); err != nil {
|
||||
return err
|
||||
|
||||
+3
@@ -58,6 +58,9 @@ func (d *devicesController) Create(path string, resources *specs.LinuxResources)
|
||||
if device.Allow {
|
||||
file = allowDeviceFile
|
||||
}
|
||||
if device.Type == "" {
|
||||
device.Type = "a"
|
||||
}
|
||||
if err := ioutil.WriteFile(
|
||||
filepath.Join(d.Path(path), file),
|
||||
[]byte(deviceString(device)),
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ func (n *netprioController) Create(path string, resources *specs.LinuxResources)
|
||||
if resources.Network != nil {
|
||||
for _, prio := range resources.Network.Priorities {
|
||||
if err := ioutil.WriteFile(
|
||||
filepath.Join(n.Path(path), "net_prio_ifpriomap"),
|
||||
filepath.Join(n.Path(path), "net_prio.ifpriomap"),
|
||||
formatPrio(prio.Name, prio.Priority),
|
||||
defaultFilePerm,
|
||||
); err != nil {
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Copyright The containerd Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cgroups
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrIgnoreSubsystem allows the specific subsystem to be skipped
|
||||
ErrIgnoreSubsystem = errors.New("skip subsystem")
|
||||
// ErrDevicesRequired is returned when the devices subsystem is required but
|
||||
// does not exist or is not active
|
||||
ErrDevicesRequired = errors.New("devices subsystem is required")
|
||||
)
|
||||
|
||||
// InitOpts allows configuration for the creation or loading of a cgroup
|
||||
type InitOpts func(*InitConfig) error
|
||||
|
||||
// InitConfig provides configuration options for the creation
|
||||
// or loading of a cgroup and its subsystems
|
||||
type InitConfig struct {
|
||||
// InitCheck can be used to check initialization errors from the subsystem
|
||||
InitCheck InitCheck
|
||||
}
|
||||
|
||||
func newInitConfig() *InitConfig {
|
||||
return &InitConfig{
|
||||
InitCheck: RequireDevices,
|
||||
}
|
||||
}
|
||||
|
||||
// InitCheck allows subsystems errors to be checked when initialized or loaded
|
||||
type InitCheck func(Subsystem, Path, error) error
|
||||
|
||||
// AllowAny allows any subsystem errors to be skipped
|
||||
func AllowAny(s Subsystem, p Path, err error) error {
|
||||
return ErrIgnoreSubsystem
|
||||
}
|
||||
|
||||
// RequireDevices requires the device subsystem but no others
|
||||
func RequireDevices(s Subsystem, p Path, err error) error {
|
||||
if s.Name() == Devices {
|
||||
return ErrDevicesRequired
|
||||
}
|
||||
return ErrIgnoreSubsystem
|
||||
}
|
||||
+4
-1
@@ -57,6 +57,9 @@ func PidPath(pid int) Path {
|
||||
return existingPath(paths, "")
|
||||
}
|
||||
|
||||
// ErrControllerNotActive is returned when a controller is not supported or enabled
|
||||
var ErrControllerNotActive = errors.New("controller is not supported")
|
||||
|
||||
func existingPath(paths map[string]string, suffix string) Path {
|
||||
// localize the paths based on the root mount dest for nested cgroups
|
||||
for n, p := range paths {
|
||||
@@ -77,7 +80,7 @@ func existingPath(paths map[string]string, suffix string) Path {
|
||||
root, ok := paths[string(name)]
|
||||
if !ok {
|
||||
if root, ok = paths[fmt.Sprintf("name=%s", name)]; !ok {
|
||||
return "", fmt.Errorf("unable to find %q in controller set", name)
|
||||
return "", ErrControllerNotActive
|
||||
}
|
||||
}
|
||||
if suffix != "" {
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ const (
|
||||
)
|
||||
|
||||
// Subsystems returns a complete list of the default cgroups
|
||||
// avaliable on most linux systems
|
||||
// available on most linux systems
|
||||
func Subsystems() []Name {
|
||||
n := []Name{
|
||||
Hugetlb,
|
||||
|
||||
+31
-2
@@ -32,6 +32,11 @@ const (
|
||||
defaultSlice = "system.slice"
|
||||
)
|
||||
|
||||
var (
|
||||
canDelegate bool
|
||||
once sync.Once
|
||||
)
|
||||
|
||||
func Systemd() ([]Subsystem, error) {
|
||||
root, err := v1MountPoint()
|
||||
if err != nil {
|
||||
@@ -54,7 +59,7 @@ func Slice(slice, name string) Path {
|
||||
slice = defaultSlice
|
||||
}
|
||||
return func(subsystem Name) (string, error) {
|
||||
return filepath.Join(slice, unitName(name)), nil
|
||||
return filepath.Join(slice, name), nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,15 +85,39 @@ func (s *SystemdController) Create(path string, resources *specs.LinuxResources)
|
||||
}
|
||||
defer conn.Close()
|
||||
slice, name := splitName(path)
|
||||
// We need to see if systemd can handle the delegate property
|
||||
// Systemd will return an error if it cannot handle delegate regardless
|
||||
// of its bool setting.
|
||||
checkDelegate := func() {
|
||||
canDelegate = true
|
||||
dlSlice := newProperty("Delegate", true)
|
||||
if _, err := conn.StartTransientUnit(slice, "testdelegate", []systemdDbus.Property{dlSlice}, nil); err != nil {
|
||||
if dbusError, ok := err.(dbus.Error); ok {
|
||||
// Starting with systemd v237, Delegate is not even a property of slices anymore,
|
||||
// so the D-Bus call fails with "InvalidArgs" error.
|
||||
if strings.Contains(dbusError.Name, "org.freedesktop.DBus.Error.PropertyReadOnly") || strings.Contains(dbusError.Name, "org.freedesktop.DBus.Error.InvalidArgs") {
|
||||
canDelegate = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
conn.StopUnit(slice, "testDelegate", nil)
|
||||
}
|
||||
once.Do(checkDelegate)
|
||||
properties := []systemdDbus.Property{
|
||||
systemdDbus.PropDescription(fmt.Sprintf("cgroup %s", name)),
|
||||
systemdDbus.PropWants(slice),
|
||||
newProperty("DefaultDependencies", false),
|
||||
newProperty("Delegate", true),
|
||||
newProperty("MemoryAccounting", true),
|
||||
newProperty("CPUAccounting", true),
|
||||
newProperty("BlockIOAccounting", true),
|
||||
}
|
||||
|
||||
// If we can delegate, we add the property back in
|
||||
if canDelegate {
|
||||
properties = append(properties, newProperty("Delegate", true))
|
||||
}
|
||||
|
||||
ch := make(chan string)
|
||||
_, err = conn.StartTransientUnit(name, "replace", properties, ch)
|
||||
if err != nil {
|
||||
|
||||
+28
-1
@@ -111,7 +111,7 @@ func remove(path string) error {
|
||||
return fmt.Errorf("cgroups: unable to remove path %q", path)
|
||||
}
|
||||
|
||||
// readPids will read all the pids in a cgroup by the provided path
|
||||
// readPids will read all the pids of processes in a cgroup by the provided path
|
||||
func readPids(path string, subsystem Name) ([]Process, error) {
|
||||
f, err := os.Open(filepath.Join(path, cgroupProcs))
|
||||
if err != nil {
|
||||
@@ -138,6 +138,33 @@ func readPids(path string, subsystem Name) ([]Process, error) {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// readTasksPids will read all the pids of tasks in a cgroup by the provided path
|
||||
func readTasksPids(path string, subsystem Name) ([]Task, error) {
|
||||
f, err := os.Open(filepath.Join(path, cgroupTasks))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
var (
|
||||
out []Task
|
||||
s = bufio.NewScanner(f)
|
||||
)
|
||||
for s.Scan() {
|
||||
if t := s.Text(); t != "" {
|
||||
pid, err := strconv.Atoi(t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, Task{
|
||||
Pid: pid,
|
||||
Subsystem: subsystem,
|
||||
Path: path,
|
||||
})
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func hugePageSizes() ([]string, error) {
|
||||
var (
|
||||
pageSizes []string
|
||||
|
||||
+175
-14
@@ -28,6 +28,7 @@ import github_com_opencontainers_go_digest "github.com/opencontainers/go-digest"
|
||||
|
||||
import strings "strings"
|
||||
import reflect "reflect"
|
||||
import sortkeys "github.com/gogo/protobuf/sortkeys"
|
||||
|
||||
import io "io"
|
||||
|
||||
@@ -48,9 +49,10 @@ const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
|
||||
// oci descriptor found in a manifest.
|
||||
// See https://godoc.org/github.com/opencontainers/image-spec/specs-go/v1#Descriptor
|
||||
type Descriptor struct {
|
||||
MediaType string `protobuf:"bytes,1,opt,name=media_type,json=mediaType,proto3" json:"media_type,omitempty"`
|
||||
Digest github_com_opencontainers_go_digest.Digest `protobuf:"bytes,2,opt,name=digest,proto3,customtype=github.com/opencontainers/go-digest.Digest" json:"digest"`
|
||||
Size_ int64 `protobuf:"varint,3,opt,name=size,proto3" json:"size,omitempty"`
|
||||
MediaType string `protobuf:"bytes,1,opt,name=media_type,json=mediaType,proto3" json:"media_type,omitempty"`
|
||||
Digest github_com_opencontainers_go_digest.Digest `protobuf:"bytes,2,opt,name=digest,proto3,customtype=github.com/opencontainers/go-digest.Digest" json:"digest"`
|
||||
Size_ int64 `protobuf:"varint,3,opt,name=size,proto3" json:"size,omitempty"`
|
||||
Annotations map[string]string `protobuf:"bytes,5,rep,name=annotations" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
}
|
||||
|
||||
func (m *Descriptor) Reset() { *m = Descriptor{} }
|
||||
@@ -92,6 +94,23 @@ func (m *Descriptor) MarshalTo(dAtA []byte) (int, error) {
|
||||
i++
|
||||
i = encodeVarintDescriptor(dAtA, i, uint64(m.Size_))
|
||||
}
|
||||
if len(m.Annotations) > 0 {
|
||||
for k, _ := range m.Annotations {
|
||||
dAtA[i] = 0x2a
|
||||
i++
|
||||
v := m.Annotations[k]
|
||||
mapSize := 1 + len(k) + sovDescriptor(uint64(len(k))) + 1 + len(v) + sovDescriptor(uint64(len(v)))
|
||||
i = encodeVarintDescriptor(dAtA, i, uint64(mapSize))
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintDescriptor(dAtA, i, uint64(len(k)))
|
||||
i += copy(dAtA[i:], k)
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintDescriptor(dAtA, i, uint64(len(v)))
|
||||
i += copy(dAtA[i:], v)
|
||||
}
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
@@ -118,6 +137,14 @@ func (m *Descriptor) Size() (n int) {
|
||||
if m.Size_ != 0 {
|
||||
n += 1 + sovDescriptor(uint64(m.Size_))
|
||||
}
|
||||
if len(m.Annotations) > 0 {
|
||||
for k, v := range m.Annotations {
|
||||
_ = k
|
||||
_ = v
|
||||
mapEntrySize := 1 + len(k) + sovDescriptor(uint64(len(k))) + 1 + len(v) + sovDescriptor(uint64(len(v)))
|
||||
n += mapEntrySize + 1 + sovDescriptor(uint64(mapEntrySize))
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
@@ -138,10 +165,21 @@ func (this *Descriptor) String() string {
|
||||
if this == nil {
|
||||
return "nil"
|
||||
}
|
||||
keysForAnnotations := make([]string, 0, len(this.Annotations))
|
||||
for k, _ := range this.Annotations {
|
||||
keysForAnnotations = append(keysForAnnotations, k)
|
||||
}
|
||||
sortkeys.Strings(keysForAnnotations)
|
||||
mapStringForAnnotations := "map[string]string{"
|
||||
for _, k := range keysForAnnotations {
|
||||
mapStringForAnnotations += fmt.Sprintf("%v: %v,", k, this.Annotations[k])
|
||||
}
|
||||
mapStringForAnnotations += "}"
|
||||
s := strings.Join([]string{`&Descriptor{`,
|
||||
`MediaType:` + fmt.Sprintf("%v", this.MediaType) + `,`,
|
||||
`Digest:` + fmt.Sprintf("%v", this.Digest) + `,`,
|
||||
`Size_:` + fmt.Sprintf("%v", this.Size_) + `,`,
|
||||
`Annotations:` + mapStringForAnnotations + `,`,
|
||||
`}`,
|
||||
}, "")
|
||||
return s
|
||||
@@ -260,6 +298,124 @@ func (m *Descriptor) Unmarshal(dAtA []byte) error {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 5:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Annotations", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDescriptor
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthDescriptor
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.Annotations == nil {
|
||||
m.Annotations = make(map[string]string)
|
||||
}
|
||||
var mapkey string
|
||||
var mapvalue string
|
||||
for iNdEx < postIndex {
|
||||
entryPreIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDescriptor
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
if fieldNum == 1 {
|
||||
var stringLenmapkey uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDescriptor
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLenmapkey |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLenmapkey := int(stringLenmapkey)
|
||||
if intStringLenmapkey < 0 {
|
||||
return ErrInvalidLengthDescriptor
|
||||
}
|
||||
postStringIndexmapkey := iNdEx + intStringLenmapkey
|
||||
if postStringIndexmapkey > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
|
||||
iNdEx = postStringIndexmapkey
|
||||
} else if fieldNum == 2 {
|
||||
var stringLenmapvalue uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowDescriptor
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLenmapvalue |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLenmapvalue := int(stringLenmapvalue)
|
||||
if intStringLenmapvalue < 0 {
|
||||
return ErrInvalidLengthDescriptor
|
||||
}
|
||||
postStringIndexmapvalue := iNdEx + intStringLenmapvalue
|
||||
if postStringIndexmapvalue > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue])
|
||||
iNdEx = postStringIndexmapvalue
|
||||
} else {
|
||||
iNdEx = entryPreIndex
|
||||
skippy, err := skipDescriptor(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthDescriptor
|
||||
}
|
||||
if (iNdEx + skippy) > postIndex {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
m.Annotations[mapkey] = mapvalue
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipDescriptor(dAtA[iNdEx:])
|
||||
@@ -391,20 +547,25 @@ func init() {
|
||||
}
|
||||
|
||||
var fileDescriptorDescriptor = []byte{
|
||||
// 234 bytes of a gzipped FileDescriptorProto
|
||||
// 311 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xb2, 0x4e, 0xcf, 0x2c, 0xc9,
|
||||
0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0xcf, 0x2b, 0x49, 0xcc, 0xcc, 0x4b, 0x2d,
|
||||
0x4a, 0x41, 0x66, 0x26, 0x16, 0x64, 0xea, 0x97, 0x54, 0x16, 0xa4, 0x16, 0xeb, 0xa7, 0xa4, 0x16,
|
||||
0x27, 0x17, 0x65, 0x16, 0x94, 0xe4, 0x17, 0xe9, 0x15, 0x14, 0xe5, 0x97, 0xe4, 0x0b, 0x09, 0x20,
|
||||
0x94, 0xe9, 0x81, 0x95, 0x48, 0x89, 0xa4, 0xe7, 0xa7, 0xe7, 0x83, 0x25, 0xf5, 0x41, 0x2c, 0x88,
|
||||
0x3a, 0xa5, 0x6e, 0x46, 0x2e, 0x2e, 0x17, 0xb8, 0x66, 0x21, 0x59, 0x2e, 0xae, 0xdc, 0xd4, 0x94,
|
||||
0xcc, 0xc4, 0x78, 0x90, 0x1e, 0x09, 0x46, 0x05, 0x46, 0x0d, 0xce, 0x20, 0x4e, 0xb0, 0x48, 0x48,
|
||||
0x65, 0x41, 0xaa, 0x90, 0x17, 0x17, 0x5b, 0x4a, 0x66, 0x7a, 0x6a, 0x71, 0x89, 0x04, 0x13, 0x48,
|
||||
0xca, 0xc9, 0xe8, 0xc4, 0x3d, 0x79, 0x86, 0x5b, 0xf7, 0xe4, 0xb5, 0x90, 0x9c, 0x9a, 0x5f, 0x90,
|
||||
0x9a, 0x07, 0xb7, 0xbc, 0x58, 0x3f, 0x3d, 0x5f, 0x17, 0xa2, 0x45, 0xcf, 0x05, 0x4c, 0x05, 0x41,
|
||||
0x4d, 0x10, 0x12, 0xe2, 0x62, 0x29, 0xce, 0xac, 0x4a, 0x95, 0x60, 0x56, 0x60, 0xd4, 0x60, 0x0e,
|
||||
0x02, 0xb3, 0x9d, 0xbc, 0x4e, 0x3c, 0x94, 0x63, 0xb8, 0xf1, 0x50, 0x8e, 0xa1, 0xe1, 0x91, 0x1c,
|
||||
0xe3, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x18, 0x65, 0x40,
|
||||
0x7c, 0x60, 0x58, 0x83, 0xc9, 0x08, 0x86, 0x24, 0x36, 0xb0, 0x17, 0x8d, 0x01, 0x01, 0x00, 0x00,
|
||||
0xff, 0xff, 0xea, 0xac, 0x78, 0x9a, 0x49, 0x01, 0x00, 0x00,
|
||||
0x3a, 0xa5, 0x39, 0x4c, 0x5c, 0x5c, 0x2e, 0x70, 0xcd, 0x42, 0xb2, 0x5c, 0x5c, 0xb9, 0xa9, 0x29,
|
||||
0x99, 0x89, 0xf1, 0x20, 0x3d, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x9c, 0x60, 0x91, 0x90,
|
||||
0xca, 0x82, 0x54, 0x21, 0x2f, 0x2e, 0xb6, 0x94, 0xcc, 0xf4, 0xd4, 0xe2, 0x12, 0x09, 0x26, 0x90,
|
||||
0x94, 0x93, 0xd1, 0x89, 0x7b, 0xf2, 0x0c, 0xb7, 0xee, 0xc9, 0x6b, 0x21, 0x39, 0x35, 0xbf, 0x20,
|
||||
0x35, 0x0f, 0x6e, 0x79, 0xb1, 0x7e, 0x7a, 0xbe, 0x2e, 0x44, 0x8b, 0x9e, 0x0b, 0x98, 0x0a, 0x82,
|
||||
0x9a, 0x20, 0x24, 0xc4, 0xc5, 0x52, 0x9c, 0x59, 0x95, 0x2a, 0xc1, 0xac, 0xc0, 0xa8, 0xc1, 0x1c,
|
||||
0x04, 0x66, 0x0b, 0xf9, 0x73, 0x71, 0x27, 0xe6, 0xe5, 0xe5, 0x97, 0x24, 0x96, 0x64, 0xe6, 0xe7,
|
||||
0x15, 0x4b, 0xb0, 0x2a, 0x30, 0x6b, 0x70, 0x1b, 0xe9, 0xea, 0xa1, 0xfb, 0x45, 0x0f, 0xe1, 0x62,
|
||||
0x3d, 0x47, 0x84, 0x7a, 0xd7, 0xbc, 0x92, 0xa2, 0xca, 0x20, 0x64, 0x13, 0xa4, 0xec, 0xb8, 0x04,
|
||||
0xd0, 0x15, 0x08, 0x09, 0x70, 0x31, 0x67, 0xa7, 0x56, 0x42, 0x3d, 0x07, 0x62, 0x0a, 0x89, 0x70,
|
||||
0xb1, 0x96, 0x25, 0xe6, 0x94, 0xa6, 0x42, 0x7c, 0x15, 0x04, 0xe1, 0x58, 0x31, 0x59, 0x30, 0x3a,
|
||||
0x79, 0x9d, 0x78, 0x28, 0xc7, 0x70, 0xe3, 0xa1, 0x1c, 0x43, 0xc3, 0x23, 0x39, 0xc6, 0x13, 0x8f,
|
||||
0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x31, 0xca, 0x80, 0xf8, 0xd8, 0xb1,
|
||||
0x06, 0x93, 0x11, 0x0c, 0x49, 0x6c, 0xe0, 0x30, 0x37, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x22,
|
||||
0x8a, 0x20, 0x4a, 0xda, 0x01, 0x00, 0x00,
|
||||
}
|
||||
|
||||
+1
@@ -15,4 +15,5 @@ message Descriptor {
|
||||
string media_type = 1;
|
||||
string digest = 2 [(gogoproto.customtype) = "github.com/opencontainers/go-digest.Digest", (gogoproto.nullable) = false];
|
||||
int64 size = 3;
|
||||
map<string, string> annotations = 5;
|
||||
}
|
||||
|
||||
+18
-8
@@ -25,6 +25,8 @@ import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Self retrieves a list of mounts for the current running process.
|
||||
@@ -41,13 +43,15 @@ func Self() ([]Info, error) {
|
||||
func parseInfoFile(r io.Reader) ([]Info, error) {
|
||||
s := bufio.NewScanner(r)
|
||||
out := []Info{}
|
||||
|
||||
var err error
|
||||
for s.Scan() {
|
||||
if err := s.Err(); err != nil {
|
||||
if err = s.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
/*
|
||||
See http://man7.org/linux/man-pages/man5/proc.5.html
|
||||
|
||||
36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue
|
||||
(1)(2)(3) (4) (5) (6) (7) (8) (9) (10) (11)
|
||||
(1) mount ID: unique identifier of the mount (may be reused after umount)
|
||||
@@ -68,7 +72,7 @@ func parseInfoFile(r io.Reader) ([]Info, error) {
|
||||
numFields := len(fields)
|
||||
if numFields < 10 {
|
||||
// should be at least 10 fields
|
||||
return nil, fmt.Errorf("Parsing '%s' failed: not enough fields (%d)", text, numFields)
|
||||
return nil, errors.Errorf("parsing '%s' failed: not enough fields (%d)", text, numFields)
|
||||
}
|
||||
p := Info{}
|
||||
// ignore any numbers parsing errors, as there should not be any
|
||||
@@ -76,13 +80,19 @@ func parseInfoFile(r io.Reader) ([]Info, error) {
|
||||
p.Parent, _ = strconv.Atoi(fields[1])
|
||||
mm := strings.Split(fields[2], ":")
|
||||
if len(mm) != 2 {
|
||||
return nil, fmt.Errorf("Parsing '%s' failed: unexpected minor:major pair %s", text, mm)
|
||||
return nil, errors.Errorf("parsing '%s' failed: unexpected minor:major pair %s", text, mm)
|
||||
}
|
||||
p.Major, _ = strconv.Atoi(mm[0])
|
||||
p.Minor, _ = strconv.Atoi(mm[1])
|
||||
|
||||
p.Root = fields[3]
|
||||
p.Mountpoint = fields[4]
|
||||
p.Root, err = strconv.Unquote(`"` + fields[3] + `"`)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "parsing '%s' failed: unable to unquote root field", fields[3])
|
||||
}
|
||||
p.Mountpoint, err = strconv.Unquote(`"` + fields[4] + `"`)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "parsing '%s' failed: unable to unquote mount point field", fields[4])
|
||||
}
|
||||
p.Options = fields[5]
|
||||
|
||||
// one or more optional fields, when a separator (-)
|
||||
@@ -101,11 +111,11 @@ func parseInfoFile(r io.Reader) ([]Info, error) {
|
||||
}
|
||||
}
|
||||
if i == numFields {
|
||||
return nil, fmt.Errorf("Parsing '%s' failed: missing separator ('-')", text)
|
||||
return nil, errors.Errorf("parsing '%s' failed: missing separator ('-')", text)
|
||||
}
|
||||
// There should be 3 fields after the separator...
|
||||
if i+4 > numFields {
|
||||
return nil, fmt.Errorf("Parsing '%s' failed: not enough fields after a separator", text)
|
||||
return nil, errors.Errorf("parsing '%s' failed: not enough fields after a separator", text)
|
||||
}
|
||||
// ... but in Linux <= 3.9 mounting a cifs with spaces in a share name
|
||||
// (like "//serv/My Documents") _may_ end up having a space in the last field
|
||||
|
||||
+4
@@ -69,4 +69,8 @@ type PlatformRuntime interface {
|
||||
// Tasks returns all the current tasks for the runtime.
|
||||
// Any container runs at most one task at a time.
|
||||
Tasks(context.Context, bool) ([]Task, error)
|
||||
// Add adds a task into runtime.
|
||||
Add(context.Context, Task) error
|
||||
// Delete remove a task.
|
||||
Delete(context.Context, string)
|
||||
}
|
||||
|
||||
+3
-6
@@ -22,6 +22,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/containerd/console"
|
||||
"github.com/containerd/containerd/errdefs"
|
||||
"github.com/containerd/containerd/runtime/proc"
|
||||
google_protobuf "github.com/gogo/protobuf/types"
|
||||
"github.com/pkg/errors"
|
||||
@@ -55,11 +56,11 @@ func (s *deletedState) Start(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (s *deletedState) Delete(ctx context.Context) error {
|
||||
return errors.Errorf("cannot delete a deleted process")
|
||||
return errors.Wrap(errdefs.ErrNotFound, "cannot delete a deleted process")
|
||||
}
|
||||
|
||||
func (s *deletedState) Kill(ctx context.Context, sig uint32, all bool) error {
|
||||
return errors.Errorf("cannot kill a deleted process")
|
||||
return errors.Wrap(errdefs.ErrNotFound, "cannot kill a deleted process")
|
||||
}
|
||||
|
||||
func (s *deletedState) SetExited(status int) {
|
||||
@@ -69,7 +70,3 @@ func (s *deletedState) SetExited(status int) {
|
||||
func (s *deletedState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
|
||||
return nil, errors.Errorf("cannot exec in a deleted state")
|
||||
}
|
||||
|
||||
func (s *deletedState) Pid() int {
|
||||
return -1
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user