This patch adds a test for the shared HOST Pid namespace

It also kills all processes in a cgroup if you are not using the pid namespace

If we stop using the PID namespace, and more then one process is running
when the pid 1 exits, docker will hang since the cgroups do not disappear.

This code will kill all remaining processes

Add Tests for handing of Pid Namespaces

Docker-DCO-1.1-Signed-off-by: Dan Walsh <dwalsh@redhat.com> (github: rhatdan)
This commit is contained in:
Dan Walsh
2015-01-07 17:19:36 -05:00
parent be02944484
commit 1bd146ed82
2 changed files with 64 additions and 2 deletions
+33 -2
View File
@@ -67,7 +67,7 @@ func TestIPCPrivate(t *testing.T) {
}
if actual := strings.Trim(buffers.Stdout.String(), "\n"); actual == l {
t.Fatalf("ipc link should be private to the conatiner but equals host %q %q", actual, l)
t.Fatalf("ipc link should be private to the container but equals host %q %q", actual, l)
}
}
@@ -152,7 +152,7 @@ func TestIPCBadPath(t *testing.T) {
_, _, err = runContainer(config, "", "true")
if err == nil {
t.Fatal("container succeded with bad ipc path")
t.Fatal("container succeeded with bad ipc path")
}
}
@@ -176,3 +176,34 @@ func TestRlimit(t *testing.T) {
t.Fatalf("expected rlimit to be 1024, got %s", limit)
}
}
func TestPIDNSPrivate(t *testing.T) {
if testing.Short() {
return
}
rootfs, err := newRootFs()
if err != nil {
t.Fatal(err)
}
defer remove(rootfs)
l, err := os.Readlink("/proc/1/ns/pid")
if err != nil {
t.Fatal(err)
}
config := newTemplateConfig(rootfs)
buffers, exitCode, err := runContainer(config, "", "readlink", "/proc/self/ns/pid")
if err != nil {
t.Fatal(err)
}
if exitCode != 0 {
t.Fatalf("exit code not 0. code %d stderr %q", exitCode, buffers.Stderr)
}
if actual := strings.Trim(buffers.Stdout.String(), "\n"); actual == l {
t.Fatalf("pid link should be private to the container but equals host %q %q", actual, l)
}
}
+31
View File
@@ -110,9 +110,40 @@ func Exec(container *libcontainer.Config, stdin io.Reader, stdout, stderr io.Wri
return -1, err
}
}
if !container.Namespaces.Contains(libcontainer.NEWPID) {
killAllPids(container)
}
return command.ProcessState.Sys().(syscall.WaitStatus).ExitStatus(), nil
}
func killAllPids(container *libcontainer.Config) {
var (
pids []int
err error
)
freeze := fs.Freeze
getPids := fs.GetPids
if systemd.UseSystemd() {
freeze = systemd.Freeze
getPids = systemd.GetPids
}
freeze(container.Cgroups, cgroups.Frozen)
if pids, err = getPids(container.Cgroups); err == nil {
for _, pid := range pids {
if p, err := os.FindProcess(pid); err == nil {
p.Kill()
}
}
}
freeze(container.Cgroups, cgroups.Thawed)
for _, pid := range pids {
if p, err := os.FindProcess(pid); err == nil {
p.Wait()
}
}
}
// DefaultCreateCommand will return an exec.Cmd with the Cloneflags set to the proper namespaces
// defined on the container's configuration and use the current binary as the init with the
// args provided