|
@@ -17,41 +17,42 @@ import (
|
|
|
|
|
|
type errNoSuchProcess struct {
|
|
|
pid int
|
|
|
- signal int
|
|
|
+ signal syscall.Signal
|
|
|
}
|
|
|
|
|
|
func (e errNoSuchProcess) Error() string {
|
|
|
- return fmt.Sprintf("Cannot kill process (pid=%d) with signal %d: no such process.", e.pid, e.signal)
|
|
|
+ return fmt.Sprintf("cannot kill process (pid=%d) with signal %d: no such process", e.pid, e.signal)
|
|
|
}
|
|
|
|
|
|
func (errNoSuchProcess) NotFound() {}
|
|
|
|
|
|
-// isErrNoSuchProcess returns true if the error
|
|
|
-// is an instance of errNoSuchProcess.
|
|
|
-func isErrNoSuchProcess(err error) bool {
|
|
|
- _, ok := err.(errNoSuchProcess)
|
|
|
- return ok
|
|
|
-}
|
|
|
-
|
|
|
// ContainerKill sends signal to the container
|
|
|
-// If no signal is given (sig 0), then Kill with SIGKILL and wait
|
|
|
+// If no signal is given, 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, stopSignal string) error {
|
|
|
+ var (
|
|
|
+ err error
|
|
|
+ sig = syscall.SIGKILL
|
|
|
+ )
|
|
|
+ if stopSignal != "" {
|
|
|
+ sig, err = signal.ParseSignal(stopSignal)
|
|
|
+ if err != nil {
|
|
|
+ return errdefs.InvalidParameter(err)
|
|
|
+ }
|
|
|
+ if !signal.ValidSignalForPlatform(sig) {
|
|
|
+ return errdefs.InvalidParameter(errors.Errorf("the %s daemon does not support signal %d", runtime.GOOS, sig))
|
|
|
+ }
|
|
|
+ }
|
|
|
container, err := daemon.GetContainer(name)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
-
|
|
|
- if sig != 0 && !signal.ValidSignalForPlatform(syscall.Signal(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 == syscall.SIGKILL {
|
|
|
+ // perform regular Kill (SIGKILL + wait())
|
|
|
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,8 @@ 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 {
|
|
|
- logrus.Debugf("Sending kill signal %d to container %s", sig, container.ID)
|
|
|
+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()
|
|
|
|
|
@@ -69,12 +70,12 @@ func (daemon *Daemon) killWithSignal(container *containerpkg.Container, sig int)
|
|
|
}
|
|
|
|
|
|
var unpause bool
|
|
|
- if container.Config.StopSignal != "" && syscall.Signal(sig) != syscall.SIGKILL {
|
|
|
+ if container.Config.StopSignal != "" && stopSignal != syscall.SIGKILL {
|
|
|
containerStopSignal, err := signal.ParseSignal(container.Config.StopSignal)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
- if containerStopSignal == syscall.Signal(sig) {
|
|
|
+ if containerStopSignal == stopSignal {
|
|
|
container.ExitOnNext()
|
|
|
unpause = container.Paused
|
|
|
}
|
|
@@ -95,7 +96,8 @@ func (daemon *Daemon) killWithSignal(container *containerpkg.Container, sig int)
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
- if err := daemon.kill(container, sig); err != nil {
|
|
|
+ err := daemon.containerd.SignalProcess(context.Background(), container.ID, libcontainerdtypes.InitProcessName, stopSignal)
|
|
|
+ if err != nil {
|
|
|
if errdefs.IsNotFound(err) {
|
|
|
unpause = false
|
|
|
logrus.WithError(err).WithField("container", container.ID).WithField("action", "kill").Debug("container kill failed because of 'container not found' or 'no such process'")
|
|
@@ -125,7 +127,7 @@ func (daemon *Daemon) killWithSignal(container *containerpkg.Container, sig int)
|
|
|
}
|
|
|
|
|
|
attributes := map[string]string{
|
|
|
- "signal": fmt.Sprintf("%d", sig),
|
|
|
+ "signal": fmt.Sprintf("%d", stopSignal),
|
|
|
}
|
|
|
daemon.LogContainerEventWithAttributes(container, "kill", attributes)
|
|
|
return nil
|
|
@@ -138,9 +140,9 @@ 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) {
|
|
|
+ if errors.As(err, &errNoSuchProcess{}) {
|
|
|
return nil
|
|
|
}
|
|
|
}
|
|
@@ -156,7 +158,7 @@ func (daemon *Daemon) Kill(container *containerpkg.Container) error {
|
|
|
logrus.WithError(status.Err()).WithField("container", container.ID).Error("Container failed to exit within 10 seconds of kill - trying direct SIGKILL")
|
|
|
|
|
|
if err := killProcessDirectly(container); err != nil {
|
|
|
- if isErrNoSuchProcess(err) {
|
|
|
+ if errors.As(err, &errNoSuchProcess{}) {
|
|
|
return nil
|
|
|
}
|
|
|
return err
|
|
@@ -173,16 +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
|
|
|
}
|
|
|
-
|
|
|
-func (daemon *Daemon) kill(c *containerpkg.Container, sig int) error {
|
|
|
- return daemon.containerd.SignalProcess(context.Background(), c.ID, libcontainerdtypes.InitProcessName, sig)
|
|
|
-}
|