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:
parent
521807837b
commit
d733481399
9 changed files with 26 additions and 30 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue