summaryrefslogtreecommitdiffhomepage
path: root/runsc/container/container.go
diff options
context:
space:
mode:
Diffstat (limited to 'runsc/container/container.go')
-rw-r--r--runsc/container/container.go98
1 files changed, 66 insertions, 32 deletions
diff --git a/runsc/container/container.go b/runsc/container/container.go
index 0820edaec..50b0dd5e7 100644
--- a/runsc/container/container.go
+++ b/runsc/container/container.go
@@ -208,7 +208,7 @@ func New(conf *config.Config, args Args) (*Container, error) {
if err := c.Saver.lockForNew(); err != nil {
return nil, err
}
- defer c.Saver.unlock()
+ defer c.Saver.unlockOrDie()
// If the metadata annotations indicate that this container should be started
// in an existing sandbox, we must do so. These are the possible metadata
@@ -310,7 +310,7 @@ func New(conf *config.Config, args Args) (*Container, error) {
defer tty.Close()
}
- if err := c.Sandbox.CreateContainer(c.ID, tty); err != nil {
+ if err := c.Sandbox.CreateSubcontainer(conf, c.ID, tty); err != nil {
return nil, err
}
}
@@ -340,7 +340,7 @@ func (c *Container) Start(conf *config.Config) error {
if err := c.Saver.lock(); err != nil {
return err
}
- unlock := cleanup.Make(func() { c.Saver.unlock() })
+ unlock := cleanup.Make(c.Saver.unlockOrDie)
defer unlock.Clean()
if err := c.requireStatus("start", Created); err != nil {
@@ -388,7 +388,7 @@ func (c *Container) Start(conf *config.Config) error {
stdios = []*os.File{os.Stdin, os.Stdout, os.Stderr}
}
- return c.Sandbox.StartContainer(c.Spec, conf, c.ID, stdios, goferFiles)
+ return c.Sandbox.StartSubcontainer(c.Spec, conf, c.ID, stdios, goferFiles)
}); err != nil {
return err
}
@@ -426,7 +426,7 @@ func (c *Container) Restore(spec *specs.Spec, conf *config.Config, restoreFile s
if err := c.Saver.lock(); err != nil {
return err
}
- defer c.Saver.unlock()
+ defer c.Saver.unlockOrDie()
if err := c.requireStatus("restore", Created); err != nil {
return err
@@ -480,13 +480,13 @@ func Run(conf *config.Config, args Args) (unix.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) {
+func (c *Container) Execute(conf *config.Config, args *control.ExecArgs) (int32, error) {
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
}
args.ContainerID = c.ID
- return c.Sandbox.Execute(args)
+ return c.Sandbox.Execute(conf, args)
}
// Event returns events for the container.
@@ -614,7 +614,7 @@ func (c *Container) Pause() error {
if err := c.Saver.lock(); err != nil {
return err
}
- defer c.Saver.unlock()
+ defer c.Saver.unlockOrDie()
if c.Status != Created && c.Status != Running {
return fmt.Errorf("cannot pause container %q in state %v", c.ID, c.Status)
@@ -634,7 +634,7 @@ func (c *Container) Resume() error {
if err := c.Saver.lock(); err != nil {
return err
}
- defer c.Saver.unlock()
+ defer c.Saver.unlockOrDie()
if c.Status != Paused {
return fmt.Errorf("cannot resume container %q in state %v", c.ID, c.Status)
@@ -646,6 +646,36 @@ func (c *Container) Resume() error {
return c.saveLocked()
}
+// Cat prints out the content of the files.
+func (c *Container) Cat(files []string, out *os.File) error {
+ log.Debugf("Cat in container, cid: %s, files: %+v", c.ID, files)
+ return c.Sandbox.Cat(c.ID, files, out)
+}
+
+// Usage displays memory used by the application.
+func (c *Container) Usage(full bool) (control.MemoryUsage, error) {
+ log.Debugf("Usage in container, cid: %s, full: %v", c.ID, full)
+ return c.Sandbox.Usage(c.ID, full)
+}
+
+// UsageFD shows application memory usage using two donated FDs.
+func (c *Container) UsageFD() (*control.MemoryUsageRecord, error) {
+ log.Debugf("UsageFD in container, cid: %s", c.ID)
+ return c.Sandbox.UsageFD(c.ID)
+}
+
+// Reduce requests that the sentry attempt to reduce its memory usage.
+func (c *Container) Reduce(wait bool) error {
+ log.Debugf("Reduce in container, cid: %s", c.ID)
+ return c.Sandbox.Reduce(c.ID, wait)
+}
+
+// Stream dumps all events to out.
+func (c *Container) Stream(filters []string, out *os.File) error {
+ log.Debugf("Stream in container, cid: %s", c.ID)
+ return c.Sandbox.Stream(c.ID, filters, out)
+}
+
// State returns the metadata of the container.
func (c *Container) State() specs.State {
return specs.State{
@@ -675,8 +705,8 @@ func (c *Container) Destroy() error {
return err
}
defer func() {
- c.Saver.unlock()
- c.Saver.close()
+ c.Saver.unlockOrDie()
+ _ = c.Saver.close()
}()
// Stored for later use as stop() sets c.Sandbox to nil.
@@ -789,30 +819,31 @@ func (c *Container) stop() error {
}
func (c *Container) waitForStopped() error {
+ if c.GoferPid == 0 {
+ return nil
+ }
+
+ if c.IsSandboxRunning() {
+ if err := c.SignalContainer(unix.Signal(0), false); err == nil {
+ return fmt.Errorf("container is still running")
+ }
+ }
+
+ if c.goferIsChild {
+ // The gofer process is a child of the current process,
+ // so we can wait it and collect its zombie.
+ if _, err := unix.Wait4(int(c.GoferPid), nil, 0, nil); err != nil {
+ return fmt.Errorf("error waiting the gofer process: %v", err)
+ }
+ c.GoferPid = 0
+ return nil
+ }
+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
b := backoff.WithContext(backoff.NewConstantBackOff(100*time.Millisecond), ctx)
op := func() error {
- if c.IsSandboxRunning() {
- if err := c.SignalContainer(unix.Signal(0), false); err == nil {
- return fmt.Errorf("container is still running")
- }
- }
- if c.GoferPid == 0 {
- return nil
- }
- if c.goferIsChild {
- // The gofer process is a child of the current process,
- // so we can wait it and collect its zombie.
- wpid, err := unix.Wait4(int(c.GoferPid), nil, unix.WNOHANG, nil)
- if err != nil {
- return fmt.Errorf("error waiting the gofer process: %v", err)
- }
- if wpid == 0 {
- return fmt.Errorf("gofer is still running")
- }
-
- } else if err := unix.Kill(c.GoferPid, 0); err == nil {
+ if err := unix.Kill(c.GoferPid, 0); err == nil {
return fmt.Errorf("gofer is still running")
}
c.GoferPid = 0
@@ -910,6 +941,9 @@ func (c *Container) createGoferProcess(spec *specs.Spec, conf *config.Config, bu
binPath := specutils.ExePath
cmd := exec.Command(binPath, args...)
cmd.ExtraFiles = goferEnds
+
+ // Set Args[0] to make easier to spot the gofer process. Otherwise it's
+ // shown as `exe`.
cmd.Args[0] = "runsc-gofer"
if attached {
@@ -1020,10 +1054,10 @@ func runInCgroup(cg *cgroup.Cgroup, fn func() error) error {
return fn()
}
restore, err := cg.Join()
- defer restore()
if err != nil {
return err
}
+ defer restore()
return fn()
}