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:
parent
2ec2b65e45
commit
ea1eb449b7
4 changed files with 24 additions and 20 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue