daemon: killWithSignal, killPossiblyDeadProcess: accept syscall.Signal

This helps reducing some type-juggling / conversions further up
the stack.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2022-05-02 00:28:17 +02:00
parent 2ec2b65e45
commit ea1eb449b7
No known key found for this signature in database
GPG key ID: 76698F39D527CE8C
4 changed files with 24 additions and 20 deletions

View file

@ -8,6 +8,7 @@ import (
"os"
"path/filepath"
"strconv"
"syscall"
"github.com/docker/docker/container"
"github.com/docker/docker/daemon/links"
@ -336,24 +337,25 @@ func (daemon *Daemon) cleanupSecretDir(c *container.Container) {
func killProcessDirectly(container *container.Container) error {
pid := container.GetPID()
// Ensure that we don't kill ourselves
if pid == 0 {
// Ensure that we don't kill ourselves
return nil
}
if err := unix.Kill(pid, 9); err != nil {
if err := unix.Kill(pid, syscall.SIGKILL); err != nil {
if err != unix.ESRCH {
return err
return errdefs.System(err)
}
e := errNoSuchProcess{pid, 9}
logrus.WithError(e).WithField("container", container.ID).Debug("no such process")
return e
err = errNoSuchProcess{pid, syscall.SIGKILL}
logrus.WithError(err).WithField("container", container.ID).Debug("no such process")
return err
}
// 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)
// TODO(thaJeztah) should we ignore os.IsNotExist() here? ("/proc/<pid>/stat" will be gone if the process exited)
if err != nil {
logrus.WithError(err).WithField("container", container.ID).Warn("Container state is invalid")
return err

View file

@ -17,7 +17,7 @@ import (
type errNoSuchProcess struct {
pid int
signal int
signal syscall.Signal
}
func (e errNoSuchProcess) Error() string {
@ -37,21 +37,22 @@ func isErrNoSuchProcess(err error) bool {
// If no signal is given (sig 0), then Kill with SIGKILL and wait
// for the container to exit.
// If a signal is given, then just send it to the container and return.
func (daemon *Daemon) ContainerKill(name string, sig uint64) error {
func (daemon *Daemon) ContainerKill(name string, stopSignal uint64) error {
sig := syscall.Signal(stopSignal)
container, err := daemon.GetContainer(name)
if err != nil {
return err
}
if sig != 0 && !signal.ValidSignalForPlatform(syscall.Signal(sig)) {
if sig != 0 && !signal.ValidSignalForPlatform(sig) {
return fmt.Errorf("The %s daemon does not support signal %d", runtime.GOOS, sig)
}
// If no signal is passed, or SIGKILL, perform regular Kill (SIGKILL + wait())
if sig == 0 || syscall.Signal(sig) == syscall.SIGKILL {
if sig == 0 || sig == syscall.SIGKILL {
return daemon.Kill(container)
}
return daemon.killWithSignal(container, int(sig))
return daemon.killWithSignal(container, sig)
}
// killWithSignal sends the container the given signal. This wrapper for the
@ -59,8 +60,7 @@ func (daemon *Daemon) ContainerKill(name string, sig uint64) error {
// to send the signal. An error is returned if the container is paused
// or not running, or if there is a problem returned from the
// underlying kill command.
func (daemon *Daemon) killWithSignal(container *containerpkg.Container, sig int) error {
var stopSignal = syscall.Signal(sig)
func (daemon *Daemon) killWithSignal(container *containerpkg.Container, stopSignal syscall.Signal) error {
logrus.Debugf("Sending kill signal %d to container %s", stopSignal, container.ID)
container.Lock()
defer container.Unlock()
@ -140,7 +140,7 @@ func (daemon *Daemon) Kill(container *containerpkg.Container) error {
}
// 1. Send SIGKILL
if err := daemon.killPossiblyDeadProcess(container, int(syscall.SIGKILL)); err != nil {
if err := daemon.killPossiblyDeadProcess(container, syscall.SIGKILL); err != nil {
// kill failed, check if process is no longer running.
if isErrNoSuchProcess(err) {
return nil
@ -175,12 +175,12 @@ func (daemon *Daemon) Kill(container *containerpkg.Container) error {
}
// killPossibleDeadProcess is a wrapper around killSig() suppressing "no such process" error.
func (daemon *Daemon) killPossiblyDeadProcess(container *containerpkg.Container, sig int) error {
func (daemon *Daemon) killPossiblyDeadProcess(container *containerpkg.Container, sig syscall.Signal) error {
err := daemon.killWithSignal(container, sig)
if errdefs.IsNotFound(err) {
e := errNoSuchProcess{container.GetPID(), sig}
logrus.Debug(e)
return e
err = errNoSuchProcess{container.GetPID(), sig}
logrus.Debug(err)
return err
}
return err
}

View file

@ -2,6 +2,7 @@ package daemon // import "github.com/docker/docker/daemon"
import (
"context"
"syscall"
"time"
containertypes "github.com/docker/docker/api/types/container"
@ -42,7 +43,7 @@ func (daemon *Daemon) containerStop(ctx context.Context, ctr *container.Containe
}
var (
stopSignal = ctr.StopSignal()
stopSignal = syscall.Signal(ctr.StopSignal())
stopTimeout = ctr.StopTimeout()
)
if options.Signal != "" {
@ -50,7 +51,7 @@ func (daemon *Daemon) containerStop(ctx context.Context, ctr *container.Containe
if err != nil {
return errdefs.InvalidParameter(err)
}
stopSignal = int(sig)
stopSignal = sig
}
if options.Timeout != nil {
stopTimeout = *options.Timeout

View file

@ -33,6 +33,7 @@ func IsProcessZombie(pid int) (bool, error) {
statPath := fmt.Sprintf("/proc/%d/stat", pid)
dataBytes, err := os.ReadFile(statPath)
if err != nil {
// TODO(thaJeztah) should we ignore os.IsNotExist() here? ("/proc/<pid>/stat" will be gone if the process exited)
return false, err
}
data := string(dataBytes)