summaryrefslogtreecommitdiffhomepage
path: root/runsc/boot/loader.go
diff options
context:
space:
mode:
Diffstat (limited to 'runsc/boot/loader.go')
-rw-r--r--runsc/boot/loader.go67
1 files changed, 53 insertions, 14 deletions
diff --git a/runsc/boot/loader.go b/runsc/boot/loader.go
index 52c251812..1e2a12280 100644
--- a/runsc/boot/loader.go
+++ b/runsc/boot/loader.go
@@ -112,9 +112,6 @@ type Loader struct {
// have the corresponding pid set.
//
// processes is guardded by mu.
- //
- // TODO: When containers are removed via `runsc delete`,
- // processes should be cleaned up.
processes map[execID]*kernel.ThreadGroup
}
@@ -385,7 +382,7 @@ func (l *Loader) run() error {
// If we are restoring, we do not want to create a process.
// l.restore is set by the container manager when a restore call is made.
if !l.restore {
- if err := setFileSystemForProcess(
+ if err := setupContainerFS(
&l.rootProcArgs,
l.spec,
l.conf,
@@ -476,7 +473,7 @@ func (l *Loader) startContainer(k *kernel.Kernel, spec *specs.Spec, conf *Config
stdioFDs := ioFDs[:3]
goferFDs := ioFDs[3:]
- if err := setFileSystemForProcess(
+ if err := setupContainerFS(
&procArgs,
spec,
conf,
@@ -519,6 +516,34 @@ func (l *Loader) startContainer(k *kernel.Kernel, spec *specs.Spec, conf *Config
return nil
}
+// destroyContainer stops a container if it is still running and cleans up its
+// filesystem.
+func (l *Loader) destroyContainer(cid string) error {
+ // First kill and wait for all processes in the container.
+ if err := l.signal(cid, int32(linux.SIGKILL), true /*all*/); err != nil {
+ return fmt.Errorf("failed to SIGKILL all container processes: %v", err)
+ }
+
+ l.mu.Lock()
+ defer l.mu.Unlock()
+
+ // Remove all container thread groups from the map.
+ for key := range l.processes {
+ if key.cid == cid {
+ delete(l.processes, key)
+ }
+ }
+
+ ctx := l.rootProcArgs.NewContext(l.k)
+ if err := destroyContainerFS(ctx, cid, l.k); err != nil {
+ return fmt.Errorf("failed to destroy filesystem for container %q: %v", cid, err)
+ }
+
+ // We made it!
+ log.Debugf("Container destroyed %q", cid)
+ return nil
+}
+
func (l *Loader) executeAsync(args *control.ExecArgs) (kernel.ThreadID, error) {
// Get the container Root Dirent from the Task, since we must run this
// process with the same Root.
@@ -669,13 +694,27 @@ func (l *Loader) signal(cid string, signo int32, all bool) error {
}
si := arch.SignalInfo{Signo: signo}
- if all {
- // Pause the kernel to prevent new processes from being created while
- // the signal is delivered. This prevents process leaks when SIGKILL is
- // sent to the entire container.
- l.k.Pause()
- defer l.k.Unpause()
- return l.k.SendContainerSignal(cid, &si)
- }
- return tg.Leader().SendSignal(&si)
+ if !all {
+ return tg.Leader().SendSignal(&si)
+ }
+
+ // Pause the kernel to prevent new processes from being created while
+ // the signal is delivered. This prevents process leaks when SIGKILL is
+ // sent to the entire container.
+ l.k.Pause()
+ if err := l.k.SendContainerSignal(cid, &si); err != nil {
+ l.k.Unpause()
+ return err
+ }
+ l.k.Unpause()
+
+ // If killing all processes, wait for them to exit.
+ if all && linux.Signal(signo) == linux.SIGKILL {
+ for _, t := range l.k.TaskSet().Root.Tasks() {
+ if t.ContainerID() == cid {
+ t.ThreadGroup().WaitExited()
+ }
+ }
+ }
+ return nil
}