From f3c1eec99e0e487bacbd016d3cb72e4c6f74f75c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B1=88=E9=AA=8F?= Date: Fri, 27 Mar 2020 11:20:41 +0800 Subject: [PATCH] add zombie check for container when killing it, alernative fix for #40735. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 屈骏 --- daemon/container_operations_unix.go | 15 +++++++++++++++ pkg/system/process_unix.go | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/daemon/container_operations_unix.go b/daemon/container_operations_unix.go index 3098cc00ad..a7f4687fa7 100644 --- a/daemon/container_operations_unix.go +++ b/daemon/container_operations_unix.go @@ -17,6 +17,7 @@ import ( "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/mount" "github.com/docker/docker/pkg/stringid" + "github.com/docker/docker/pkg/system" "github.com/docker/docker/runconfig" "github.com/docker/libnetwork" "github.com/opencontainers/selinux/go-selinux/label" @@ -353,6 +354,20 @@ func killProcessDirectly(cntr *container.Container) error { logrus.Debug(e) return e } + + // In case there were some exceptions(e.g., state of zombie and D) + if system.IsProcessAlive(pid) { + + // Since we can not kill a zombie pid, add zombie check here + isZombie, err := system.IsProcessZombie(pid) + if err != nil { + logrus.Warnf("Container %s state is invalid", stringid.TruncateID(cntr.ID)) + return err + } + if isZombie { + return errdefs.System(errors.Errorf("container %s PID %d is zombie and can not be killed. Use the --init option when creating containers to run an init inside the container that forwards signals and reaps processes", stringid.TruncateID(cntr.ID), pid)) + } + } } } return nil diff --git a/pkg/system/process_unix.go b/pkg/system/process_unix.go index 0195a891b2..79aebb5272 100644 --- a/pkg/system/process_unix.go +++ b/pkg/system/process_unix.go @@ -3,6 +3,9 @@ package system // import "github.com/docker/docker/pkg/system" import ( + "fmt" + "io/ioutil" + "strings" "syscall" "golang.org/x/sys/unix" @@ -22,3 +25,20 @@ func IsProcessAlive(pid int) bool { func KillProcess(pid int) { unix.Kill(pid, unix.SIGKILL) } + +// IsProcessZombie return true if process has a state with "Z" +// http://man7.org/linux/man-pages/man5/proc.5.html +func IsProcessZombie(pid int) (bool, error) { + statPath := fmt.Sprintf("/proc/%d/stat", pid) + dataBytes, err := ioutil.ReadFile(statPath) + if err != nil { + return false, err + } + data := string(dataBytes) + sdata := strings.SplitN(data, " ", 4) + if len(sdata) >= 3 && sdata[2] == "Z" { + return true, nil + } + + return false, nil +}