Skip to content

Commit 3f52663

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

File tree

2 files changed

+32
-11
lines changed

2 files changed

+32
-11
lines changed

daemon/container_operations_unix.go

+15-5
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 {
363-
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))
360+
// Since we can not kill a zombie and D status pid, add check here
361+
if status != "" {
362+
switch status {
363+
case "D":
364+
return errdefs.System(errors.Errorf("container %s PID %d is uninterruptible and can not be killed", stringid.TruncateID(container.ID), pid))
365+
case "Z":
366+
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))
367+
case "R", "S":
368+
return errdefs.System(errors.Errorf("container %s PID %d is %s", stringid.TruncateID(container.ID), pid, status))
369+
case "T", "X", "x":
370+
default:
371+
// If process can't be killed and status is not D or Z print some warning log.It is almost impossible to happen.
372+
logrus.Warnf("container %s PID %d status is \"%s\"", container.ID, pid, status)
373+
}
364374
}
365375
}
366376
return nil

pkg/process/process_unix.go

+17-6
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)