daemon: daemon.ContainerKill() accept stop-signal as string

This allows the postContainersKill() handler to pass values as-is. As part of
the rewrite, I also moved the daemon.GetContainer(name) call later in the
function, so that we can fail early if an invalid signal is passed, before
doing the (heavier) fetching of the container.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2022-05-02 01:00:09 +02:00
parent 521807837b
commit d733481399
No known key found for this signature in database
GPG key ID: 76698F39D527CE8C
9 changed files with 26 additions and 30 deletions

View file

@ -33,7 +33,7 @@ type copyBackend interface {
// stateBackend includes functions to implement to provide container state lifecycle functionality. // stateBackend includes functions to implement to provide container state lifecycle functionality.
type stateBackend interface { type stateBackend interface {
ContainerCreate(config types.ContainerCreateConfig) (container.CreateResponse, error) ContainerCreate(config types.ContainerCreateConfig) (container.CreateResponse, error)
ContainerKill(name string, sig uint64) error ContainerKill(name string, signal string) error
ContainerPause(name string) error ContainerPause(name string) error
ContainerRename(oldName, newName string) error ContainerRename(oldName, newName string) error
ContainerResize(name string, height, width int) error ContainerResize(name string, height, width int) error

View file

@ -7,7 +7,6 @@ import (
"io" "io"
"net/http" "net/http"
"strconv" "strconv"
"syscall"
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
"github.com/docker/docker/api/server/httpstatus" "github.com/docker/docker/api/server/httpstatus"
@ -254,18 +253,8 @@ func (s *containerRouter) postContainersKill(ctx context.Context, w http.Respons
return err return err
} }
var sig syscall.Signal
name := vars["name"] name := vars["name"]
if err := s.backend.ContainerKill(name, r.Form.Get("signal")); err != nil {
// If we have a signal, look at it. Otherwise, do nothing
if sigStr := r.Form.Get("signal"); sigStr != "" {
var err error
if sig, err = signal.ParseSignal(sigStr); err != nil {
return errdefs.InvalidParameter(err)
}
}
if err := s.backend.ContainerKill(name, uint64(sig)); err != nil {
var isStopped bool var isStopped bool
if errdefs.IsConflict(err) { if errdefs.IsConflict(err) {
isStopped = true isStopped = true

View file

@ -65,7 +65,7 @@ type ExecBackend interface {
// ContainerRm removes a container specified by `id`. // ContainerRm removes a container specified by `id`.
ContainerRm(name string, config *types.ContainerRmConfig) error ContainerRm(name string, config *types.ContainerRmConfig) error
// ContainerKill stops the container execution abruptly. // ContainerKill stops the container execution abruptly.
ContainerKill(containerID string, sig uint64) error ContainerKill(containerID string, sig string) error
// ContainerStart starts a new container // ContainerStart starts a new container
ContainerStart(containerID string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error ContainerStart(containerID string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
// ContainerWait stops processing until the given container is stopped. // ContainerWait stops processing until the given container is stopped.

View file

@ -61,7 +61,7 @@ func (c *containerManager) Run(ctx context.Context, cID string, stdout, stderr i
select { select {
case <-ctx.Done(): case <-ctx.Done():
logrus.Debugln("Build cancelled, killing and removing container:", cID) logrus.Debugln("Build cancelled, killing and removing container:", cID)
c.backend.ContainerKill(cID, 0) c.backend.ContainerKill(cID, "")
c.removeContainer(cID, stdout) c.removeContainer(cID, stdout)
cancelErrCh <- errCancelled cancelErrCh <- errCancelled
case <-finished: case <-finished:

View file

@ -46,7 +46,7 @@ func (m *MockBackend) CommitBuildStep(c backend.CommitConfig) (image.ID, error)
return "", nil return "", nil
} }
func (m *MockBackend) ContainerKill(containerID string, sig uint64) error { func (m *MockBackend) ContainerKill(containerID string, sig string) error {
return nil return nil
} }
@ -129,7 +129,7 @@ func (l *mockLayer) NewRWLayer() (builder.RWLayer, error) {
} }
func (l *mockLayer) DiffID() layer.DiffID { func (l *mockLayer) DiffID() layer.DiffID {
return layer.DiffID("abcdef") return "abcdef"
} }
type mockRWLayer struct { type mockRWLayer struct {

View file

@ -45,7 +45,7 @@ type Backend interface {
ContainerInspectCurrent(name string, size bool) (*types.ContainerJSON, error) ContainerInspectCurrent(name string, size bool) (*types.ContainerJSON, error)
ContainerWait(ctx context.Context, name string, condition containerpkg.WaitCondition) (<-chan containerpkg.StateStatus, error) ContainerWait(ctx context.Context, name string, condition containerpkg.WaitCondition) (<-chan containerpkg.StateStatus, error)
ContainerRm(name string, config *types.ContainerRmConfig) error ContainerRm(name string, config *types.ContainerRmConfig) error
ContainerKill(name string, sig uint64) error ContainerKill(name string, sig string) error
SetContainerDependencyStore(name string, store exec.DependencyGetter) error SetContainerDependencyStore(name string, store exec.DependencyGetter) error
SetContainerSecretReferences(name string, refs []*swarmtypes.SecretReference) error SetContainerSecretReferences(name string, refs []*swarmtypes.SecretReference) error
SetContainerConfigReferences(name string, refs []*swarmtypes.ConfigReference) error SetContainerConfigReferences(name string, refs []*swarmtypes.ConfigReference) error

View file

@ -417,7 +417,7 @@ func (c *containerAdapter) shutdown(ctx context.Context) error {
} }
func (c *containerAdapter) terminate(ctx context.Context) error { func (c *containerAdapter) terminate(ctx context.Context) error {
return c.backend.ContainerKill(c.container.name(), uint64(syscall.SIGKILL)) return c.backend.ContainerKill(c.container.name(), syscall.SIGKILL.String())
} }
func (c *containerAdapter) remove(ctx context.Context) error { func (c *containerAdapter) remove(ctx context.Context) error {

View file

@ -34,22 +34,29 @@ func isErrNoSuchProcess(err error) bool {
} }
// ContainerKill sends signal to the container // 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. // for the container to exit.
// If a signal is given, then just send it to the container and return. // If a signal is given, then just send it to the container and return.
func (daemon *Daemon) ContainerKill(name string, stopSignal uint64) error { func (daemon *Daemon) ContainerKill(name, stopSignal string) error {
sig := syscall.Signal(stopSignal) 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) container, err := daemon.GetContainer(name)
if err != nil { if err != nil {
return err return err
} }
if sig == syscall.SIGKILL {
if sig != 0 && !signal.ValidSignalForPlatform(sig) { // perform regular Kill (SIGKILL + wait())
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 || sig == syscall.SIGKILL {
return daemon.Kill(container) return daemon.Kill(container)
} }
return daemon.killWithSignal(container, sig) return daemon.killWithSignal(container, sig)

View file

@ -688,7 +688,7 @@ func (c *client) Exec(ctx context.Context, containerID, processID string, spec *
// SignalProcess handles `docker stop` on Windows. While Linux has support for // SignalProcess handles `docker stop` on Windows. While Linux has support for
// the full range of signals, signals aren't really implemented on Windows. // the full range of signals, signals aren't really implemented on Windows.
// We fake supporting regular stop and -9 to force kill. // We fake supporting regular stop and -9 to force kill.
func (c *client) SignalProcess(_ context.Context, containerID, processID string, signal int) error { func (c *client) SignalProcess(_ context.Context, containerID, processID string, signal syscall.Signal) error {
ctr, p, err := c.getProcess(containerID, processID) ctr, p, err := c.getProcess(containerID, processID)
if err != nil { if err != nil {
return err return err