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.go62
1 files changed, 43 insertions, 19 deletions
diff --git a/runsc/container/container.go b/runsc/container/container.go
index 07924d23a..dc9ef86fa 100644
--- a/runsc/container/container.go
+++ b/runsc/container/container.go
@@ -36,6 +36,7 @@ import (
"gvisor.googlesource.com/gvisor/pkg/log"
"gvisor.googlesource.com/gvisor/pkg/sentry/control"
"gvisor.googlesource.com/gvisor/runsc/boot"
+ "gvisor.googlesource.com/gvisor/runsc/cgroup"
"gvisor.googlesource.com/gvisor/runsc/sandbox"
"gvisor.googlesource.com/gvisor/runsc/specutils"
)
@@ -286,18 +287,26 @@ func Create(id string, spec *specs.Spec, conf *boot.Config, bundleDir, consoleSo
return nil, fmt.Errorf("writing clean spec: %v", err)
}
- ioFiles, err := c.createGoferProcess(spec, conf, bundleDir)
- if err != nil {
- return nil, err
+ // Create and join cgroup before processes are created to ensure they are
+ // part of the cgroup from the start (and all tneir children processes).
+ cg := cgroup.New(spec)
+ if cg != nil {
+ // If there is cgroup config, install it before creating sandbox process.
+ if err := cg.Install(spec.Linux.Resources); err != nil {
+ return nil, fmt.Errorf("configuring cgroup: %v", err)
+ }
}
+ if err := runInCgroup(cg, func() error {
+ ioFiles, err := c.createGoferProcess(spec, conf, bundleDir)
+ if err != nil {
+ return err
+ }
- // Start a new sandbox for this container. Any errors after this point
- // must destroy the container.
- c.Sandbox, err = sandbox.Create(id, spec, conf, bundleDir, consoleSocket, userLog, ioFiles)
- if err != nil {
- return nil, err
- }
- if err := c.Sandbox.AddGoferToCgroup(c.GoferPid); err != nil {
+ // Start a new sandbox for this container. Any errors after this point
+ // must destroy the container.
+ c.Sandbox, err = sandbox.New(id, spec, conf, bundleDir, consoleSocket, userLog, ioFiles, cg)
+ return err
+ }); err != nil {
return nil, err
}
} else {
@@ -381,15 +390,16 @@ func (c *Container) Start(conf *boot.Config) error {
return fmt.Errorf("writing clean spec: %v", err)
}
- // Create the gofer process.
- ioFiles, err := c.createGoferProcess(c.Spec, conf, c.BundleDir)
- if err != nil {
- return err
- }
- if err := c.Sandbox.StartContainer(c.Spec, conf, c.ID, ioFiles); err != nil {
- return err
- }
- if err := c.Sandbox.AddGoferToCgroup(c.GoferPid); err != nil {
+ // Join cgroup to strt gofer process to ensure it's part of the cgroup from
+ // the start (and all tneir children processes).
+ if err := runInCgroup(c.Sandbox.Cgroup, func() error {
+ // Create the gofer process.
+ ioFiles, err := c.createGoferProcess(c.Spec, conf, c.BundleDir)
+ if err != nil {
+ return err
+ }
+ return c.Sandbox.StartContainer(c.Spec, conf, c.ID, ioFiles)
+ }); err != nil {
return err
}
}
@@ -883,3 +893,17 @@ func lockContainerMetadata(containerRootDir string) (func() error, error) {
}
return l.Unlock, nil
}
+
+// runInCgroup executes fn inside the specified cgroup. If cg is nil, execute
+// it in the current context.
+func runInCgroup(cg *cgroup.Cgroup, fn func() error) error {
+ if cg == nil {
+ return fn()
+ }
+ restore, err := cg.Join()
+ defer restore()
+ if err != nil {
+ return err
+ }
+ return fn()
+}