summaryrefslogtreecommitdiffhomepage
path: root/runsc
diff options
context:
space:
mode:
authorgVisor bot <gvisor-bot@google.com>2020-11-05 23:39:45 +0000
committergVisor bot <gvisor-bot@google.com>2020-11-05 23:39:45 +0000
commit00810031aa23fdfa996572ca22b565db108c3666 (patch)
treed3e36d3b9e831aec582fb572f3a820a9f3d6ccbd /runsc
parent715a6085fcc34c138a4e3ec7b3acc41266d10d15 (diff)
parentc47f8afe2334c1395a2acd9ebf5191aa4554907c (diff)
Merge release-20201030.0-32-gc47f8afe2 (automated)
Diffstat (limited to 'runsc')
-rw-r--r--runsc/boot/controller.go31
-rw-r--r--runsc/boot/loader.go2
-rw-r--r--runsc/cmd/checkpoint.go2
-rw-r--r--runsc/cmd/debug.go4
-rw-r--r--runsc/cmd/delete.go2
-rw-r--r--runsc/cmd/events.go2
-rw-r--r--runsc/cmd/exec.go2
-rw-r--r--runsc/cmd/kill.go2
-rw-r--r--runsc/cmd/list.go2
-rw-r--r--runsc/cmd/pause.go2
-rw-r--r--runsc/cmd/ps.go2
-rw-r--r--runsc/cmd/resume.go2
-rw-r--r--runsc/cmd/start.go2
-rw-r--r--runsc/cmd/state.go2
-rw-r--r--runsc/cmd/wait.go2
-rw-r--r--runsc/container/container.go156
-rw-r--r--runsc/sandbox/sandbox.go13
-rw-r--r--runsc/specutils/specutils.go29
18 files changed, 117 insertions, 142 deletions
diff --git a/runsc/boot/controller.go b/runsc/boot/controller.go
index 4e0f0d57a..fdf13c8e1 100644
--- a/runsc/boot/controller.go
+++ b/runsc/boot/controller.go
@@ -196,7 +196,7 @@ type containerManager struct {
// StartRoot will start the root container process.
func (cm *containerManager) StartRoot(cid *string, _ *struct{}) error {
- log.Debugf("containerManager.StartRoot %q", *cid)
+ log.Debugf("containerManager.StartRoot, cid: %s", *cid)
// Tell the root container to start and wait for the result.
cm.startChan <- struct{}{}
if err := <-cm.startResultChan; err != nil {
@@ -207,13 +207,13 @@ func (cm *containerManager) StartRoot(cid *string, _ *struct{}) error {
// Processes retrieves information about processes running in the sandbox.
func (cm *containerManager) Processes(cid *string, out *[]*control.Process) error {
- log.Debugf("containerManager.Processes: %q", *cid)
+ log.Debugf("containerManager.Processes, cid: %s", *cid)
return control.Processes(cm.l.k, *cid, out)
}
// Create creates a container within a sandbox.
func (cm *containerManager) Create(cid *string, _ *struct{}) error {
- log.Debugf("containerManager.Create: %q", *cid)
+ log.Debugf("containerManager.Create, cid: %s", *cid)
return cm.l.createContainer(*cid)
}
@@ -237,12 +237,11 @@ type StartArgs struct {
// Start runs a created container within a sandbox.
func (cm *containerManager) Start(args *StartArgs, _ *struct{}) error {
- log.Debugf("containerManager.Start: %+v", args)
-
// Validate arguments.
if args == nil {
return errors.New("start missing arguments")
}
+ log.Debugf("containerManager.Start, cid: %s, args: %+v", args.CID, args)
if args.Spec == nil {
return errors.New("start arguments missing spec")
}
@@ -269,27 +268,27 @@ func (cm *containerManager) Start(args *StartArgs, _ *struct{}) error {
}
}()
if err := cm.l.startContainer(args.Spec, args.Conf, args.CID, fds); err != nil {
- log.Debugf("containerManager.Start failed %q: %+v: %v", args.CID, args, err)
+ log.Debugf("containerManager.Start failed, cid: %s, args: %+v, err: %v", args.CID, args, err)
return err
}
- log.Debugf("Container %q started", args.CID)
+ log.Debugf("Container started, cid: %s", args.CID)
return nil
}
// Destroy stops a container if it is still running and cleans up its
// filesystem.
func (cm *containerManager) Destroy(cid *string, _ *struct{}) error {
- log.Debugf("containerManager.destroy %q", *cid)
+ log.Debugf("containerManager.destroy, cid: %s", *cid)
return cm.l.destroyContainer(*cid)
}
// ExecuteAsync starts running a command on a created or running sandbox. It
// returns the PID of the new process.
func (cm *containerManager) ExecuteAsync(args *control.ExecArgs, pid *int32) error {
- log.Debugf("containerManager.ExecuteAsync: %+v", args)
+ log.Debugf("containerManager.ExecuteAsync, cid: %s, args: %+v", args.ContainerID, args)
tgid, err := cm.l.executeAsync(args)
if err != nil {
- log.Debugf("containerManager.ExecuteAsync failed: %+v: %v", args, err)
+ log.Debugf("containerManager.ExecuteAsync failed, cid: %s, args: %+v, err: %v", args.ContainerID, args, err)
return err
}
*pid = int32(tgid)
@@ -453,9 +452,9 @@ func (cm *containerManager) Resume(_, _ *struct{}) error {
// Wait waits for the init process in the given container.
func (cm *containerManager) Wait(cid *string, waitStatus *uint32) error {
- log.Debugf("containerManager.Wait")
+ log.Debugf("containerManager.Wait, cid: %s", *cid)
err := cm.l.waitContainer(*cid, waitStatus)
- log.Debugf("containerManager.Wait returned, waitStatus: %v: %v", waitStatus, err)
+ log.Debugf("containerManager.Wait returned, cid: %s, waitStatus: %#x, err: %v", *cid, *waitStatus, err)
return err
}
@@ -470,8 +469,10 @@ type WaitPIDArgs struct {
// WaitPID waits for the process with PID 'pid' in the sandbox.
func (cm *containerManager) WaitPID(args *WaitPIDArgs, waitStatus *uint32) error {
- log.Debugf("containerManager.Wait")
- return cm.l.waitPID(kernel.ThreadID(args.PID), args.CID, waitStatus)
+ log.Debugf("containerManager.Wait, cid: %s, pid: %d", args.CID, args.PID)
+ err := cm.l.waitPID(kernel.ThreadID(args.PID), args.CID, waitStatus)
+ log.Debugf("containerManager.Wait, cid: %s, pid: %d, waitStatus: %#x, err: %v", args.CID, args.PID, *waitStatus, err)
+ return err
}
// SignalDeliveryMode enumerates different signal delivery modes.
@@ -528,6 +529,6 @@ type SignalArgs struct {
// indicated process, to all processes in the container, or to the foreground
// process group.
func (cm *containerManager) Signal(args *SignalArgs, _ *struct{}) error {
- log.Debugf("containerManager.Signal %+v", args)
+ log.Debugf("containerManager.Signal: cid: %s, PID: %d, signal: %d, mode: %v", args.CID, args.PID, args.Signo, args.Mode)
return cm.l.signal(args.CID, args.PID, args.Signo, args.Mode)
}
diff --git a/runsc/boot/loader.go b/runsc/boot/loader.go
index db2b0cea7..ebdd518d0 100644
--- a/runsc/boot/loader.go
+++ b/runsc/boot/loader.go
@@ -888,7 +888,7 @@ func (l *Loader) destroyContainer(cid string) error {
}
}
- log.Debugf("Container destroyed %q", cid)
+ log.Debugf("Container destroyed, cid: %s", cid)
return nil
}
diff --git a/runsc/cmd/checkpoint.go b/runsc/cmd/checkpoint.go
index d4e0da2ab..c0bc8f064 100644
--- a/runsc/cmd/checkpoint.go
+++ b/runsc/cmd/checkpoint.go
@@ -75,7 +75,7 @@ func (c *Checkpoint) Execute(_ context.Context, f *flag.FlagSet, args ...interfa
conf := args[0].(*config.Config)
waitStatus := args[1].(*syscall.WaitStatus)
- cont, err := container.Load(conf.RootDir, id)
+ cont, err := container.LoadAndCheck(conf.RootDir, id)
if err != nil {
Fatalf("loading container: %v", err)
}
diff --git a/runsc/cmd/debug.go b/runsc/cmd/debug.go
index 132198222..609e8231c 100644
--- a/runsc/cmd/debug.go
+++ b/runsc/cmd/debug.go
@@ -91,7 +91,7 @@ func (d *Debug) Execute(_ context.Context, f *flag.FlagSet, args ...interface{})
return subcommands.ExitUsageError
}
var err error
- c, err = container.Load(conf.RootDir, f.Arg(0))
+ c, err = container.LoadAndCheck(conf.RootDir, f.Arg(0))
if err != nil {
return Errorf("loading container %q: %v", f.Arg(0), err)
}
@@ -106,7 +106,7 @@ func (d *Debug) Execute(_ context.Context, f *flag.FlagSet, args ...interface{})
return Errorf("listing containers: %v", err)
}
for _, id := range ids {
- candidate, err := container.Load(conf.RootDir, id)
+ candidate, err := container.LoadAndCheck(conf.RootDir, id)
if err != nil {
return Errorf("loading container %q: %v", id, err)
}
diff --git a/runsc/cmd/delete.go b/runsc/cmd/delete.go
index 4e49deff8..a25637265 100644
--- a/runsc/cmd/delete.go
+++ b/runsc/cmd/delete.go
@@ -68,7 +68,7 @@ func (d *Delete) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}
func (d *Delete) execute(ids []string, conf *config.Config) error {
for _, id := range ids {
- c, err := container.Load(conf.RootDir, id)
+ c, err := container.LoadAndCheck(conf.RootDir, id)
if err != nil {
if os.IsNotExist(err) && d.force {
log.Warningf("couldn't find container %q: %v", id, err)
diff --git a/runsc/cmd/events.go b/runsc/cmd/events.go
index 25fe2cf1c..5211ad4ce 100644
--- a/runsc/cmd/events.go
+++ b/runsc/cmd/events.go
@@ -74,7 +74,7 @@ func (evs *Events) Execute(ctx context.Context, f *flag.FlagSet, args ...interfa
id := f.Arg(0)
conf := args[0].(*config.Config)
- c, err := container.Load(conf.RootDir, id)
+ c, err := container.LoadAndCheck(conf.RootDir, id)
if err != nil {
Fatalf("loading sandbox: %v", err)
}
diff --git a/runsc/cmd/exec.go b/runsc/cmd/exec.go
index 775ed4b43..86c02a22a 100644
--- a/runsc/cmd/exec.go
+++ b/runsc/cmd/exec.go
@@ -112,7 +112,7 @@ func (ex *Exec) Execute(_ context.Context, f *flag.FlagSet, args ...interface{})
}
waitStatus := args[1].(*syscall.WaitStatus)
- c, err := container.Load(conf.RootDir, id)
+ c, err := container.LoadAndCheck(conf.RootDir, id)
if err != nil {
Fatalf("loading sandbox: %v", err)
}
diff --git a/runsc/cmd/kill.go b/runsc/cmd/kill.go
index 04eee99b2..fe69e2a08 100644
--- a/runsc/cmd/kill.go
+++ b/runsc/cmd/kill.go
@@ -69,7 +69,7 @@ func (k *Kill) Execute(_ context.Context, f *flag.FlagSet, args ...interface{})
Fatalf("it is invalid to specify both --all and --pid")
}
- c, err := container.Load(conf.RootDir, id)
+ c, err := container.LoadAndCheck(conf.RootDir, id)
if err != nil {
Fatalf("loading container: %v", err)
}
diff --git a/runsc/cmd/list.go b/runsc/cmd/list.go
index f92d6fef9..6907eb16a 100644
--- a/runsc/cmd/list.go
+++ b/runsc/cmd/list.go
@@ -79,7 +79,7 @@ func (l *List) Execute(_ context.Context, f *flag.FlagSet, args ...interface{})
// Collect the containers.
var containers []*container.Container
for _, id := range ids {
- c, err := container.Load(conf.RootDir, id)
+ c, err := container.LoadAndCheck(conf.RootDir, id)
if err != nil {
Fatalf("loading container %q: %v", id, err)
}
diff --git a/runsc/cmd/pause.go b/runsc/cmd/pause.go
index 0eb1402ed..fe7d4e257 100644
--- a/runsc/cmd/pause.go
+++ b/runsc/cmd/pause.go
@@ -55,7 +55,7 @@ func (*Pause) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) s
id := f.Arg(0)
conf := args[0].(*config.Config)
- cont, err := container.Load(conf.RootDir, id)
+ cont, err := container.LoadAndCheck(conf.RootDir, id)
if err != nil {
Fatalf("loading container: %v", err)
}
diff --git a/runsc/cmd/ps.go b/runsc/cmd/ps.go
index bc58c928f..18d7a1436 100644
--- a/runsc/cmd/ps.go
+++ b/runsc/cmd/ps.go
@@ -60,7 +60,7 @@ func (ps *PS) Execute(ctx context.Context, f *flag.FlagSet, args ...interface{})
id := f.Arg(0)
conf := args[0].(*config.Config)
- c, err := container.Load(conf.RootDir, id)
+ c, err := container.LoadAndCheck(conf.RootDir, id)
if err != nil {
Fatalf("loading sandbox: %v", err)
}
diff --git a/runsc/cmd/resume.go b/runsc/cmd/resume.go
index f24823f99..a00928204 100644
--- a/runsc/cmd/resume.go
+++ b/runsc/cmd/resume.go
@@ -56,7 +56,7 @@ func (r *Resume) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}
id := f.Arg(0)
conf := args[0].(*config.Config)
- cont, err := container.Load(conf.RootDir, id)
+ cont, err := container.LoadAndCheck(conf.RootDir, id)
if err != nil {
Fatalf("loading container: %v", err)
}
diff --git a/runsc/cmd/start.go b/runsc/cmd/start.go
index 139edbd49..f6499cc44 100644
--- a/runsc/cmd/start.go
+++ b/runsc/cmd/start.go
@@ -55,7 +55,7 @@ func (*Start) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) s
id := f.Arg(0)
conf := args[0].(*config.Config)
- c, err := container.Load(conf.RootDir, id)
+ c, err := container.LoadAndCheck(conf.RootDir, id)
if err != nil {
Fatalf("loading container: %v", err)
}
diff --git a/runsc/cmd/state.go b/runsc/cmd/state.go
index 2bd2ab9f8..d8a70dd7f 100644
--- a/runsc/cmd/state.go
+++ b/runsc/cmd/state.go
@@ -57,7 +57,7 @@ func (*State) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) s
id := f.Arg(0)
conf := args[0].(*config.Config)
- c, err := container.Load(conf.RootDir, id)
+ c, err := container.LoadAndCheck(conf.RootDir, id)
if err != nil {
Fatalf("loading container: %v", err)
}
diff --git a/runsc/cmd/wait.go b/runsc/cmd/wait.go
index 28d0642ed..c1d6aeae2 100644
--- a/runsc/cmd/wait.go
+++ b/runsc/cmd/wait.go
@@ -72,7 +72,7 @@ func (wt *Wait) Execute(_ context.Context, f *flag.FlagSet, args ...interface{})
id := f.Arg(0)
conf := args[0].(*config.Config)
- c, err := container.Load(conf.RootDir, id)
+ c, err := container.LoadAndCheck(conf.RootDir, id)
if err != nil {
Fatalf("loading container: %v", err)
}
diff --git a/runsc/container/container.go b/runsc/container/container.go
index 52e1755ce..435d866f5 100644
--- a/runsc/container/container.go
+++ b/runsc/container/container.go
@@ -159,9 +159,9 @@ func loadSandbox(rootDir, id string) ([]*Container, error) {
// container to which id unambiguously refers to. Returns ErrNotExist if
// container doesn't exist.
func Load(rootDir, partialID string) (*Container, error) {
- log.Debugf("Load container %q %q", rootDir, partialID)
+ log.Debugf("Load container, rootDir: %q, partial cid: %s", rootDir, partialID)
if err := validateID(partialID); err != nil {
- return nil, fmt.Errorf("validating id: %v", err)
+ return nil, fmt.Errorf("invalid container id: %v", err)
}
id, err := findContainerID(rootDir, partialID)
@@ -184,22 +184,31 @@ func Load(rootDir, partialID string) (*Container, error) {
}
return nil, fmt.Errorf("reading container metadata file %q: %v", state.statePath(), err)
}
+ return c, nil
+}
+
+// LoadAndCheck is similar to Load(), but also checks if the container is still
+// running to get an error earlier to the caller.
+func LoadAndCheck(rootDir, partialID string) (*Container, error) {
+ c, err := Load(rootDir, partialID)
+ if err != nil {
+ // Preserve error so that callers can distinguish 'not found' errors.
+ return nil, err
+ }
- // If the status is "Running" or "Created", check that the sandbox
- // process still exists, and set it to Stopped if it does not.
+ // If the status is "Running" or "Created", check that the sandbox/container
+ // is still running, setting it to Stopped if not.
//
// This is inherently racy.
- if c.Status == Running || c.Status == Created {
- // Check if the sandbox process is still running.
+ switch c.Status {
+ case Created:
if !c.isSandboxRunning() {
// Sandbox no longer exists, so this container definitely does not exist.
c.changeStatus(Stopped)
- } else if c.Status == Running {
- // Container state should reflect the actual state of the application, so
- // we don't consider gofer process here.
- if err := c.SignalContainer(syscall.Signal(0), false); err != nil {
- c.changeStatus(Stopped)
- }
+ }
+ case Running:
+ if err := c.SignalContainer(syscall.Signal(0), false); err != nil {
+ c.changeStatus(Stopped)
}
}
@@ -271,7 +280,7 @@ type Args struct {
// indicates that an existing Sandbox should be used. The caller must call
// Destroy() on the container.
func New(conf *config.Config, args Args) (*Container, error) {
- log.Debugf("Create container %q in root dir: %s", args.ID, conf.RootDir)
+ log.Debugf("Create container, cid: %s, rootDir: %q", args.ID, conf.RootDir)
if err := validateID(args.ID); err != nil {
return nil, err
}
@@ -310,7 +319,7 @@ func New(conf *config.Config, args Args) (*Container, error) {
// indicate the ID of the sandbox, which is the same as the ID of the
// init container in the sandbox.
if isRoot(args.Spec) {
- log.Debugf("Creating new sandbox for container %q", args.ID)
+ log.Debugf("Creating new sandbox for container, cid: %s", args.ID)
if args.Spec.Linux == nil {
args.Spec.Linux = &specs.Linux{}
@@ -380,10 +389,10 @@ func New(conf *config.Config, args Args) (*Container, error) {
if !ok {
return nil, fmt.Errorf("no sandbox ID found when creating container")
}
- log.Debugf("Creating new container %q in sandbox %q", c.ID, sbid)
+ log.Debugf("Creating new container, cid: %s, sandbox: %s", c.ID, sbid)
// Find the sandbox associated with this ID.
- sb, err := Load(conf.RootDir, sbid)
+ sb, err := LoadAndCheck(conf.RootDir, sbid)
if err != nil {
return nil, err
}
@@ -413,7 +422,7 @@ func New(conf *config.Config, args Args) (*Container, error) {
// Start starts running the containerized process inside the sandbox.
func (c *Container) Start(conf *config.Config) error {
- log.Debugf("Start container %q", c.ID)
+ log.Debugf("Start container, cid: %s", c.ID)
if err := c.Saver.lock(); err != nil {
return err
@@ -476,7 +485,7 @@ func (c *Container) Start(conf *config.Config) error {
unlock.Clean()
// Adjust the oom_score_adj for sandbox. This must be done after saveLocked().
- if err := adjustSandboxOOMScoreAdj(c.Sandbox, c.Saver.RootDir, false); err != nil {
+ if err := adjustSandboxOOMScoreAdj(c.Sandbox, c.Spec, c.Saver.RootDir, false); err != nil {
return err
}
@@ -488,7 +497,7 @@ func (c *Container) Start(conf *config.Config) error {
// Restore takes a container and replaces its kernel and file system
// to restore a container from its state file.
func (c *Container) Restore(spec *specs.Spec, conf *config.Config, restoreFile string) error {
- log.Debugf("Restore container %q", c.ID)
+ log.Debugf("Restore container, cid: %s", c.ID)
if err := c.Saver.lock(); err != nil {
return err
}
@@ -515,7 +524,7 @@ func (c *Container) Restore(spec *specs.Spec, conf *config.Config, restoreFile s
// Run is a helper that calls Create + Start + Wait.
func Run(conf *config.Config, args Args) (syscall.WaitStatus, error) {
- log.Debugf("Run container %q in root dir: %s", args.ID, conf.RootDir)
+ log.Debugf("Run container, cid: %s, rootDir: %q", args.ID, conf.RootDir)
c, err := New(conf, args)
if err != nil {
return 0, fmt.Errorf("creating container: %v", err)
@@ -547,7 +556,7 @@ func Run(conf *config.Config, args Args) (syscall.WaitStatus, error) {
// Execute runs the specified command in the container. It returns the PID of
// the newly created process.
func (c *Container) Execute(args *control.ExecArgs) (int32, error) {
- log.Debugf("Execute in container %q, args: %+v", c.ID, args)
+ log.Debugf("Execute in container, cid: %s, args: %+v", c.ID, args)
if err := c.requireStatus("execute in", Created, Running); err != nil {
return 0, err
}
@@ -557,7 +566,7 @@ func (c *Container) Execute(args *control.ExecArgs) (int32, error) {
// Event returns events for the container.
func (c *Container) Event() (*boot.Event, error) {
- log.Debugf("Getting events for container %q", c.ID)
+ log.Debugf("Getting events for container, cid: %s", c.ID)
if err := c.requireStatus("get events for", Created, Running, Paused); err != nil {
return nil, err
}
@@ -577,14 +586,14 @@ func (c *Container) SandboxPid() int {
// Call to wait on a stopped container is needed to retrieve the exit status
// and wait returns immediately.
func (c *Container) Wait() (syscall.WaitStatus, error) {
- log.Debugf("Wait on container %q", c.ID)
+ log.Debugf("Wait on container, cid: %s", c.ID)
return c.Sandbox.Wait(c.ID)
}
// WaitRootPID waits for process 'pid' in the sandbox's PID namespace and
// returns its WaitStatus.
func (c *Container) WaitRootPID(pid int32) (syscall.WaitStatus, error) {
- log.Debugf("Wait on PID %d in sandbox %q", pid, c.Sandbox.ID)
+ log.Debugf("Wait on process %d in sandbox, cid: %s", pid, c.Sandbox.ID)
if !c.isSandboxRunning() {
return 0, fmt.Errorf("sandbox is not running")
}
@@ -594,7 +603,7 @@ func (c *Container) WaitRootPID(pid int32) (syscall.WaitStatus, error) {
// WaitPID waits for process 'pid' in the container's PID namespace and returns
// its WaitStatus.
func (c *Container) WaitPID(pid int32) (syscall.WaitStatus, error) {
- log.Debugf("Wait on PID %d in container %q", pid, c.ID)
+ log.Debugf("Wait on process %d in container, cid: %s", pid, c.ID)
if !c.isSandboxRunning() {
return 0, fmt.Errorf("sandbox is not running")
}
@@ -606,7 +615,7 @@ func (c *Container) WaitPID(pid int32) (syscall.WaitStatus, error) {
// SignalContainer returns an error if the container is already stopped.
// TODO(b/113680494): Distinguish different error types.
func (c *Container) SignalContainer(sig syscall.Signal, all bool) error {
- log.Debugf("Signal container %q: %v", c.ID, sig)
+ log.Debugf("Signal container, cid: %s, signal: %v (%d)", c.ID, sig, sig)
// Signaling container in Stopped state is allowed. When all=false,
// an error will be returned anyway; when all=true, this allows
// sending signal to other processes inside the container even
@@ -623,7 +632,7 @@ func (c *Container) SignalContainer(sig syscall.Signal, all bool) error {
// SignalProcess sends sig to a specific process in the container.
func (c *Container) SignalProcess(sig syscall.Signal, pid int32) error {
- log.Debugf("Signal process %d in container %q: %v", pid, c.ID, sig)
+ log.Debugf("Signal process %d in container, cid: %s, signal: %v (%d)", pid, c.ID, sig, sig)
if err := c.requireStatus("signal a process inside", Running); err != nil {
return err
}
@@ -637,15 +646,15 @@ func (c *Container) SignalProcess(sig syscall.Signal, pid int32) error {
// container process inside the sandbox. It returns a function that will stop
// forwarding signals.
func (c *Container) ForwardSignals(pid int32, fgProcess bool) func() {
- log.Debugf("Forwarding all signals to container %q PID %d fgProcess=%t", c.ID, pid, fgProcess)
+ log.Debugf("Forwarding all signals to container, cid: %s, PIDPID: %d, fgProcess: %t", c.ID, pid, fgProcess)
stop := sighandling.StartSignalForwarding(func(sig linux.Signal) {
- log.Debugf("Forwarding signal %d to container %q PID %d fgProcess=%t", sig, c.ID, pid, fgProcess)
+ log.Debugf("Forwarding signal %d to container, cid: %s, PID: %d, fgProcess: %t", sig, c.ID, pid, fgProcess)
if err := c.Sandbox.SignalProcess(c.ID, pid, syscall.Signal(sig), fgProcess); err != nil {
log.Warningf("error forwarding signal %d to container %q: %v", sig, c.ID, err)
}
})
return func() {
- log.Debugf("Done forwarding signals to container %q PID %d fgProcess=%t", c.ID, pid, fgProcess)
+ log.Debugf("Done forwarding signals to container, cid: %s, PID: %d, fgProcess: %t", c.ID, pid, fgProcess)
stop()
}
}
@@ -653,7 +662,7 @@ func (c *Container) ForwardSignals(pid int32, fgProcess bool) func() {
// Checkpoint sends the checkpoint call to the container.
// The statefile will be written to f, the file at the specified image-path.
func (c *Container) Checkpoint(f *os.File) error {
- log.Debugf("Checkpoint container %q", c.ID)
+ log.Debugf("Checkpoint container, cid: %s", c.ID)
if err := c.requireStatus("checkpoint", Created, Running, Paused); err != nil {
return err
}
@@ -663,7 +672,7 @@ func (c *Container) Checkpoint(f *os.File) error {
// Pause suspends the container and its kernel.
// The call only succeeds if the container's status is created or running.
func (c *Container) Pause() error {
- log.Debugf("Pausing container %q", c.ID)
+ log.Debugf("Pausing container, cid: %s", c.ID)
if err := c.Saver.lock(); err != nil {
return err
}
@@ -674,7 +683,7 @@ func (c *Container) Pause() error {
}
if err := c.Sandbox.Pause(c.ID); err != nil {
- return fmt.Errorf("pausing container: %v", err)
+ return fmt.Errorf("pausing container %q: %v", c.ID, err)
}
c.changeStatus(Paused)
return c.saveLocked()
@@ -683,7 +692,7 @@ func (c *Container) Pause() error {
// Resume unpauses the container and its kernel.
// The call only succeeds if the container's status is paused.
func (c *Container) Resume() error {
- log.Debugf("Resuming container %q", c.ID)
+ log.Debugf("Resuming container, cid: %s", c.ID)
if err := c.Saver.lock(); err != nil {
return err
}
@@ -722,7 +731,7 @@ func (c *Container) Processes() ([]*control.Process, error) {
// Destroy stops all processes and frees all resources associated with the
// container.
func (c *Container) Destroy() error {
- log.Debugf("Destroy container %q", c.ID)
+ log.Debugf("Destroy container, cid: %s", c.ID)
if err := c.Saver.lock(); err != nil {
return err
@@ -759,14 +768,12 @@ func (c *Container) Destroy() error {
c.changeStatus(Stopped)
// Adjust oom_score_adj for the sandbox. This must be done after the container
- // is stopped and the directory at c.Root is removed. Adjustment can be
- // skipped if the root container is exiting, because it brings down the entire
- // sandbox.
+ // is stopped and the directory at c.Root is removed.
//
// Use 'sb' to tell whether it has been executed before because Destroy must
// be idempotent.
- if sb != nil && !isRoot(c.Spec) {
- if err := adjustSandboxOOMScoreAdj(sb, c.Saver.RootDir, true); err != nil {
+ if sb != nil {
+ if err := adjustSandboxOOMScoreAdj(sb, c.Spec, c.Saver.RootDir, true); err != nil {
errs = append(errs, err.Error())
}
}
@@ -795,7 +802,7 @@ func (c *Container) Destroy() error {
//
// Precondition: container must be locked with container.lock().
func (c *Container) saveLocked() error {
- log.Debugf("Save container %q", c.ID)
+ log.Debugf("Save container, cid: %s", c.ID)
if err := c.Saver.saveLocked(c); err != nil {
return fmt.Errorf("saving container metadata: %v", err)
}
@@ -809,7 +816,7 @@ func (c *Container) stop() error {
var cgroup *cgroup.Cgroup
if c.Sandbox != nil {
- log.Debugf("Destroying container %q", c.ID)
+ log.Debugf("Destroying container, cid: %s", c.ID)
if err := c.Sandbox.DestroyContainer(c.ID); err != nil {
return fmt.Errorf("destroying container %q: %v", c.ID, err)
}
@@ -823,7 +830,7 @@ func (c *Container) stop() error {
// Try killing gofer if it does not exit with container.
if c.GoferPid != 0 {
- log.Debugf("Killing gofer for container %q, PID: %d", c.ID, c.GoferPid)
+ log.Debugf("Killing gofer for container, cid: %s, PID: %d", c.ID, c.GoferPid)
if err := syscall.Kill(c.GoferPid, syscall.SIGKILL); err != nil {
// The gofer may already be stopped, log the error.
log.Warningf("Error sending signal %d to gofer %d: %v", syscall.SIGKILL, c.GoferPid, err)
@@ -1096,7 +1103,13 @@ func (c *Container) adjustGoferOOMScoreAdj() error {
// TODO(gvisor.dev/issue/238): This call could race with other containers being
// created at the same time and end up setting the wrong oom_score_adj to the
// sandbox. Use rpc client to synchronize.
-func adjustSandboxOOMScoreAdj(s *sandbox.Sandbox, rootDir string, destroy bool) error {
+func adjustSandboxOOMScoreAdj(s *sandbox.Sandbox, spec *specs.Spec, rootDir string, destroy bool) error {
+ // Adjustment can be skipped if the root container is exiting, because it
+ // brings down the entire sandbox.
+ if isRoot(spec) && destroy {
+ return nil
+ }
+
containers, err := loadSandbox(rootDir, s.ID)
if err != nil {
return fmt.Errorf("loading sandbox containers: %v", err)
@@ -1110,53 +1123,34 @@ func adjustSandboxOOMScoreAdj(s *sandbox.Sandbox, rootDir string, destroy bool)
// Get the lowest score for all containers.
var lowScore int
scoreFound := false
- if len(containers) == 1 && specutils.SpecContainerType(containers[0].Spec) == specutils.ContainerTypeUnspecified {
- // This is a single-container sandbox. Set the oom_score_adj to
- // the value specified in the OCI bundle.
- if containers[0].Spec.Process.OOMScoreAdj != nil {
- scoreFound = true
- lowScore = *containers[0].Spec.Process.OOMScoreAdj
+ for _, container := range containers {
+ // Special multi-container support for CRI. Ignore the root container when
+ // calculating oom_score_adj for the sandbox because it is the
+ // infrastructure (pause) container and always has a very low oom_score_adj.
+ //
+ // We will use OOMScoreAdj in the single-container case where the
+ // containerd container-type annotation is not present.
+ if specutils.SpecContainerType(container.Spec) == specutils.ContainerTypeSandbox {
+ continue
}
- } else {
- for _, container := range containers {
- // Special multi-container support for CRI. Ignore the root
- // container when calculating oom_score_adj for the sandbox because
- // it is the infrastructure (pause) container and always has a very
- // low oom_score_adj.
- //
- // We will use OOMScoreAdj in the single-container case where the
- // containerd container-type annotation is not present.
- if specutils.SpecContainerType(container.Spec) == specutils.ContainerTypeSandbox {
- continue
- }
- if container.Spec.Process.OOMScoreAdj != nil && (!scoreFound || *container.Spec.Process.OOMScoreAdj < lowScore) {
- scoreFound = true
- lowScore = *container.Spec.Process.OOMScoreAdj
- }
+ if container.Spec.Process.OOMScoreAdj != nil && (!scoreFound || *container.Spec.Process.OOMScoreAdj < lowScore) {
+ scoreFound = true
+ lowScore = *container.Spec.Process.OOMScoreAdj
}
}
// If the container is destroyed and remaining containers have no
- // oomScoreAdj specified then we must revert to the oom_score_adj of the
- // parent process.
+ // oomScoreAdj specified then we must revert to the original oom_score_adj
+ // saved with the root container.
if !scoreFound && destroy {
- ppid, err := specutils.GetParentPid(s.Pid)
- if err != nil {
- return fmt.Errorf("getting parent pid of sandbox pid %d: %v", s.Pid, err)
- }
- pScore, err := specutils.GetOOMScoreAdj(ppid)
- if err != nil {
- return fmt.Errorf("getting oom_score_adj of parent %d: %v", ppid, err)
- }
-
+ lowScore = containers[0].Sandbox.OriginalOOMScoreAdj
scoreFound = true
- lowScore = pScore
}
- // Only set oom_score_adj if one of the containers has oom_score_adj set
- // in the OCI bundle. If not, we need to inherit the parent process's
- // oom_score_adj.
+ // Only set oom_score_adj if one of the containers has oom_score_adj set. If
+ // not, oom_score_adj is inherited from the parent process.
+ //
// See: https://github.com/opencontainers/runtime-spec/blob/master/config.md#linux-process
if !scoreFound {
return nil
diff --git a/runsc/sandbox/sandbox.go b/runsc/sandbox/sandbox.go
index c4309feb3..4a4110477 100644
--- a/runsc/sandbox/sandbox.go
+++ b/runsc/sandbox/sandbox.go
@@ -66,6 +66,10 @@ type Sandbox struct {
// Cgroup has the cgroup configuration for the sandbox.
Cgroup *cgroup.Cgroup `json:"cgroup"`
+ // OriginalOOMScoreAdj stores the value of oom_score_adj when the sandbox
+ // started, before it may be modified.
+ OriginalOOMScoreAdj int `json:"originalOomScoreAdj"`
+
// child is set if a sandbox process is a child of the current process.
//
// This field isn't saved to json, because only a creator of sandbox
@@ -739,6 +743,11 @@ func (s *Sandbox) createSandboxProcess(conf *config.Config, args *Args, startSyn
}
return err
}
+ s.OriginalOOMScoreAdj, err = specutils.GetOOMScoreAdj(cmd.Process.Pid)
+ if err != nil {
+ return err
+ }
+
s.child = true
s.Pid = cmd.Process.Pid
log.Infof("Sandbox started, PID: %d", s.Pid)
@@ -1133,11 +1142,11 @@ func (s *Sandbox) DestroyContainer(cid string) error {
func (s *Sandbox) destroyContainer(cid string) error {
if s.IsRootContainer(cid) {
- log.Debugf("Destroying root container %q by destroying sandbox", cid)
+ log.Debugf("Destroying root container by destroying sandbox, cid: %s", cid)
return s.destroy()
}
- log.Debugf("Destroying container %q in sandbox %q", cid, s.ID)
+ log.Debugf("Destroying container, cid: %s, sandbox: %s", cid, s.ID)
conn, err := s.sandboxConnect()
if err != nil {
return err
diff --git a/runsc/specutils/specutils.go b/runsc/specutils/specutils.go
index 7b923ddf4..fdbba1832 100644
--- a/runsc/specutils/specutils.go
+++ b/runsc/specutils/specutils.go
@@ -481,35 +481,6 @@ func GetOOMScoreAdj(pid int) (int, error) {
return strconv.Atoi(strings.TrimSpace(string(data)))
}
-// GetParentPid gets the parent process ID of the specified PID.
-func GetParentPid(pid int) (int, error) {
- data, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/stat", pid))
- if err != nil {
- return 0, err
- }
-
- var cpid string
- var name string
- var state string
- var ppid int
- // Parse after the binary name.
- _, err = fmt.Sscanf(string(data),
- "%v %v %v %d",
- // cpid is ignored.
- &cpid,
- // name is ignored.
- &name,
- // state is ignored.
- &state,
- &ppid)
-
- if err != nil {
- return 0, err
- }
-
- return ppid, nil
-}
-
// EnvVar looks for a varible value in the env slice assuming the following
// format: "NAME=VALUE".
func EnvVar(env []string, name string) (string, bool) {