Skip to content

Commit 678a7b0

Browse files
committed
add D status check for container when killing it
Signed-off-by: ningmingxiao <[email protected]>
1 parent a978888 commit 678a7b0

File tree

2 files changed

+31
-10
lines changed

2 files changed

+31
-10
lines changed

daemon/container_operations_unix.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -351,16 +351,26 @@ func killProcessDirectly(container *container.Container) error {
351351
return err
352352
}
353353

354-
// In case there were some exceptions(e.g., state of zombie and D)
355354
if process.Alive(pid) {
356-
// Since we can not kill a zombie pid, add zombie check here
357-
isZombie, err := process.Zombie(pid)
355+
status, err := process.Status(pid)
358356
if err != nil {
359357
logrus.WithError(err).WithField("container", container.ID).Warn("Container state is invalid")
360358
return err
361359
}
362-
if isZombie {
360+
// Since we can not kill a zombie and D status pid, add check here
361+
switch status {
362+
case "D":
363+
return errdefs.System(errors.Errorf("container %s PID %d is uninterruptible and can not be killed", stringid.TruncateID(container.ID), pid))
364+
case "Z":
363365
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(container.ID), pid))
366+
case "S":
367+
return errdefs.System(errors.Errorf("container %s PID %d is %s and can not be killed", stringid.TruncateID(container.ID), pid, status))
368+
case "T", "X", "x":
369+
case "":
370+
return errdefs.System(errors.Errorf("container %s PID %d status is nil", stringid.TruncateID(container.ID), pid))
371+
default:
372+
// If process can't be killed and status is not D or Z print some warning log.It is almost impossible to happen.
373+
logrus.Warnf("container %s PID %d status is \"%s\"", container.ID, pid, status)
364374
}
365375
}
366376
return nil

pkg/process/process_unix.go

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,18 +64,29 @@ func Kill(pid int) error {
6464
//
6565
// [PROC(5)]: https://man7.org/linux/man-pages/man5/proc.5.html
6666
func Zombie(pid int) (bool, error) {
67+
status, err := Status(pid)
68+
return status == "Z", err
69+
}
70+
71+
// Status returns the status of the given process. It only considers positive
72+
// PIDs; 0 (all processes in the current process group), -1 (all processes with
73+
// a PID larger than 1), and negative (-n, all processes in process group "n")
74+
// values for pid are ignored. Refer to [PROC(5)] for details.
75+
//
76+
// [PROC(5)]: https://man7.org/linux/man-pages/man5/proc.5.html
77+
func Status(pid int) (string, error) {
6778
if pid < 1 {
68-
return false, nil
79+
return "", nil
6980
}
7081
data, err := os.ReadFile(fmt.Sprintf("/proc/%d/stat", pid))
7182
if err != nil {
7283
if os.IsNotExist(err) {
73-
return false, nil
84+
return "", nil
7485
}
75-
return false, err
86+
return "", err
7687
}
77-
if cols := bytes.SplitN(data, []byte(" "), 4); len(cols) >= 3 && string(cols[2]) == "Z" {
78-
return true, nil
88+
if cols := bytes.SplitN(data, []byte(" "), 4); len(cols) >= 3 {
89+
return string(cols[2]), nil
7990
}
80-
return false, nil
91+
return "", nil
8192
}

0 commit comments

Comments
 (0)