| ... | ... |
@@ -17,6 +17,7 @@ import ( |
| 17 | 17 |
"github.com/docker/docker/pkg/idtools" |
| 18 | 18 |
"github.com/docker/docker/pkg/mount" |
| 19 | 19 |
"github.com/docker/docker/pkg/stringid" |
| 20 |
+ "github.com/docker/docker/pkg/system" |
|
| 20 | 21 |
"github.com/docker/docker/runconfig" |
| 21 | 22 |
"github.com/docker/libnetwork" |
| 22 | 23 |
"github.com/opencontainers/selinux/go-selinux/label" |
| ... | ... |
@@ -353,6 +354,20 @@ func killProcessDirectly(cntr *container.Container) error {
|
| 353 | 353 |
logrus.Debug(e) |
| 354 | 354 |
return e |
| 355 | 355 |
} |
| 356 |
+ |
|
| 357 |
+ // In case there were some exceptions(e.g., state of zombie and D) |
|
| 358 |
+ if system.IsProcessAlive(pid) {
|
|
| 359 |
+ |
|
| 360 |
+ // Since we can not kill a zombie pid, add zombie check here |
|
| 361 |
+ isZombie, err := system.IsProcessZombie(pid) |
|
| 362 |
+ if err != nil {
|
|
| 363 |
+ logrus.Warnf("Container %s state is invalid", stringid.TruncateID(cntr.ID))
|
|
| 364 |
+ return err |
|
| 365 |
+ } |
|
| 366 |
+ if isZombie {
|
|
| 367 |
+ 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))
|
|
| 368 |
+ } |
|
| 369 |
+ } |
|
| 356 | 370 |
} |
| 357 | 371 |
} |
| 358 | 372 |
return nil |
| ... | ... |
@@ -3,6 +3,9 @@ |
| 3 | 3 |
package system // import "github.com/docker/docker/pkg/system" |
| 4 | 4 |
|
| 5 | 5 |
import ( |
| 6 |
+ "fmt" |
|
| 7 |
+ "io/ioutil" |
|
| 8 |
+ "strings" |
|
| 6 | 9 |
"syscall" |
| 7 | 10 |
|
| 8 | 11 |
"golang.org/x/sys/unix" |
| ... | ... |
@@ -22,3 +25,20 @@ func IsProcessAlive(pid int) bool {
|
| 22 | 22 |
func KillProcess(pid int) {
|
| 23 | 23 |
unix.Kill(pid, unix.SIGKILL) |
| 24 | 24 |
} |
| 25 |
+ |
|
| 26 |
+// IsProcessZombie return true if process has a state with "Z" |
|
| 27 |
+// http://man7.org/linux/man-pages/man5/proc.5.html |
|
| 28 |
+func IsProcessZombie(pid int) (bool, error) {
|
|
| 29 |
+ statPath := fmt.Sprintf("/proc/%d/stat", pid)
|
|
| 30 |
+ dataBytes, err := ioutil.ReadFile(statPath) |
|
| 31 |
+ if err != nil {
|
|
| 32 |
+ return false, err |
|
| 33 |
+ } |
|
| 34 |
+ data := string(dataBytes) |
|
| 35 |
+ sdata := strings.SplitN(data, " ", 4) |
|
| 36 |
+ if len(sdata) >= 3 && sdata[2] == "Z" {
|
|
| 37 |
+ return true, nil |
|
| 38 |
+ } |
|
| 39 |
+ |
|
| 40 |
+ return false, nil |
|
| 41 |
+} |