diff --git a/.travis.yml b/.travis.yml index 86d3630904..e0fcd9548f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,6 @@ language: go go: - 1.8.x - - tip go_import_path: github.com/containerd/containerd @@ -17,7 +16,7 @@ addons: - curl env: - - SECCOMP_VERSION=2.3.1 RUNC_COMMIT=9a01140955fba11a1c2927a9b273e9c837e3e30a + - SECCOMP_VERSION=2.3.1 RUNC_COMMIT=d40db12e72a40109dfcf28539f5ee0930d2f0277 install: diff --git a/Dockerfile b/Dockerfile index edd8654351..51a8427f09 100644 --- a/Dockerfile +++ b/Dockerfile @@ -59,7 +59,7 @@ RUN set -x \ && rm -rf "$SECCOMP_PATH" # Install runc -ENV RUNC_COMMIT 992a5be178a62e026f4069f443c6164912adbf09 +ENV RUNC_COMMIT d40db12e72a40109dfcf28539f5ee0930d2f0277 RUN set -x \ && export GOPATH="$(mktemp -d)" \ && git clone git://github.com/opencontainers/runc.git "$GOPATH/src/github.com/opencontainers/runc" \ diff --git a/containerd-shim/main.go b/containerd-shim/main.go index 6b59f4eef2..95208cf789 100644 --- a/containerd-shim/main.go +++ b/containerd-shim/main.go @@ -7,10 +7,11 @@ import ( "os/signal" "path/filepath" "runtime" + "sync" "syscall" - "github.com/containerd/containerd/osutils" "github.com/containerd/console" + "github.com/containerd/containerd/osutils" ) func writeMessage(f *os.File, level string, err error) { @@ -111,7 +112,10 @@ func start(log *os.File) error { if runtime.GOOS == "solaris" { return nil } - var exitShim bool + var ( + exitShim bool + cleanOnce sync.Once + ) for { select { case s := <-signals: @@ -128,15 +132,19 @@ func start(log *os.File) error { } // runtime has exited so the shim can also exit if exitShim { - // kill all processes in the container incase it was not running in - // its own PID namespace - p.killAll() - // wait for all the processes and IO to finish - p.Wait() - // delete the container from the runtime - p.delete() - // the close of the exit fifo will happen when the shim exits - return nil + cleanOnce.Do(func() { + go func() { + // kill all processes in the container incase it was not running in + // its own PID namespace + p.killAll() + // wait for all the processes and IO to finish + p.Wait() + // delete the container from the runtime + p.delete() + // the close of the exit fifo will happen when the shim exits + os.Exit(0) + }() + }) } case msg := <-msgC: switch msg.Type { diff --git a/integration-test/exec_test.go b/integration-test/exec_test.go index 62b99ed90b..c22f5c2bca 100644 --- a/integration-test/exec_test.go +++ b/integration-test/exec_test.go @@ -458,3 +458,56 @@ func (cs *ContainerdSuite) TestExecKillShimNoPanic(t *check.C) { t.Assert(err, checker.Equals, nil) t.Assert(len(containers), checker.Equals, 0) } + +func (cs *ContainerdSuite) TestBusyboxTopExecShDefunct(t *check.C) { + bundleName := "busybox-top" + if err := CreateBusyboxBundle(bundleName, []string{"top"}); err != nil { + t.Fatal(err) + } + + var ( + err error + initp *ContainerProcess + ) + + containerID := "top" + initp, err = cs.StartContainer(containerID, bundleName) + t.Assert(err, checker.Equals, nil) + + execID := "sh" + p, err := cs.AddProcessToContainer(initp, execID, "/", []string{"PATH=/bin"}, []string{"sh"}, 0, 0) + t.Assert(err, checker.Equals, nil) + + for _, evt := range []types.Event{ + { + Type: "start-container", + Id: containerID, + Status: 0, + Pid: "", + }, + { + Type: "start-process", + Id: containerID, + Status: 0, + Pid: execID, + }, + } { + ch := initp.GetEventsChannel() + e := <-ch + evt.Timestamp = e.Timestamp + t.Assert(*e, checker.Equals, evt) + } + + p.io.stdinf.Write([]byte("sleep 1000&\n")) + p.io.stdinf.Write([]byte("sleep 1&\n")) + p.io.stdinf.Write([]byte("exit\n")) + p.CloseStdin() + + <-time.After(2 * time.Second) + + b, err := exec.Command("ps", "afx").CombinedOutput() + t.Assert(err, checker.Equals, nil) + t.Assert(string(b), checker.Not(checker.Contains), "") + + cs.KillContainer(containerID) +}