API: add "signal" parameter to container stop and restart endpoints
When reviewing https://github.com/moby/moby/pull/41548, I recalled I had this branch, but never opened it as a PR, as I was planning to do so after https://github.com/moby/moby/pull/42774 was merged.

depends on / includes:

- https://github.com/moby/moby/pull/42774

## API: add "signal" parameter to container stop and restart endpoints

Containers can have a default stop-signal (`--stop-signal` / `STOPSIGNAL`) and
timeout (`--stop-timeout`). It is currently not possible to update either of
these after the container is created (`docker update` does not allow updating
them), and while either of these can be overridden through some commands, we
currently do not have a command that can override *both*:

command         | stop-signal | stop-timeout | notes
----------------|-------------|--------------|----------------------------
docker kill     | yes         | DNA          | only sends a single signal
docker restart  | no          | yes          |
docker stop     | no          | yes          |

As a result, if a user wants to stop a container with a custom signal and
timeout, the only option is to do this manually:

```bash
docker kill -s <custom signal> mycontainer
# wait <desired timeout>
# press ^C to cancel the graceful stop
# forcibly kill the container
docker kill mycontainer
```

This patch adds a new `signal` query parameter to the container "stop" and
"restart" endpoints. This parameter can be added as a new flag on the CLI,
which would allow stopping and restarting with a custom timeout and signal,
for example:

    docker stop --signal=SIGWINCH --time=120 mycontainer

    docker restart --signal=SIGWINCH --time=120 mycontainer

## Refactoring / cleanup commits

### daemon/delete: rename var that collided with import, remove output var (part of https://github.com/moby/moby/pull/42774)

Renamed a variable that collided with an import.

Also remove the named return variable from cleanupContainer(), as it wasn't used.

### daemon: cleanupContainer(): pass ContainerRmConfig as parameter (part of https://github.com/moby/moby/pull/42774)

We already have this config, so might as well pass it, instead of passing each option as a separate argument.
 
### daemon: fix inconsistent receiver name and package aliases

My IDE kept complaining about this one, so let's rename it
 
### daemon/stop: rename imports and variables to standard naming

This is in preparation of some changes, but keeping it in  a separate commit to make review of other changes easier.
 
### daemon: move default stop-timeout to containerStop()

This avoids having to determine what the default is in various parts of the code. If no custom timeout is passed (nil), the default will be used.

Also remove the named return variable from cleanupContainer(), as it wasn't used.

### daemon: containerStop(): use a regular "defer" to log container event
 
### backend: add StopConfig to ContainerRestart and ContainerStop

And while we're modifying the interface, also add a context to both


daemon/stop.go
package daemon // import "github.com/docker/docker/daemon"

import (
	"context"
	"time"

	containerpkg "github.com/docker/docker/container"
	"github.com/docker/docker/errdefs"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

// ContainerStop looks for the given container and stops it.
// In case the container fails to stop gracefully within a time duration
// specified by the timeout argument, in seconds, it is forcefully
// terminated (killed).
//
// If the timeout is nil, the container's StopTimeout value is used, if set,
// otherwise the engine default. A negative timeout value can be specified,
// meaning no timeout, i.e. no forceful termination is performed.
func (daemon *Daemon) ContainerStop(name string, timeout *int) error {
	container, err := daemon.GetContainer(name)
	if err != nil {
		return err
	}
	if !container.IsRunning() {
		return containerNotModifiedError{running: false}
	}
	if timeout == nil {
		stopTimeout := container.StopTimeout()
		timeout = &stopTimeout
	}
	if err := daemon.containerStop(container, *timeout); err != nil {
		return errdefs.System(errors.Wrapf(err, "cannot stop container: %s", name))
	}
	return nil
}

// containerStop sends a stop signal, waits, sends a kill signal.
func (daemon *Daemon) containerStop(container *containerpkg.Container, seconds int) error {
	// TODO propagate a context down to this function
	ctx := context.TODO()
	if !container.IsRunning() {
		return nil
	}
	var wait time.Duration
	if seconds >= 0 {
		wait = time.Duration(seconds) * time.Second
	}
	success := func() error {
		daemon.LogContainerEvent(container, "stop")
		return nil
	}
	stopSignal := container.StopSignal()

	// 1. Send a stop signal
	err := daemon.killPossiblyDeadProcess(container, stopSignal)
	if err != nil {
		wait = 2 * time.Second
	}

	var subCtx context.Context
	var cancel context.CancelFunc
	if seconds >= 0 {
		subCtx, cancel = context.WithTimeout(ctx, wait)
	} else {
		subCtx, cancel = context.WithCancel(ctx)
	}
	defer cancel()

	if status := <-container.Wait(subCtx, containerpkg.WaitConditionNotRunning); status.Err() == nil {
		// container did exit, so ignore any previous errors and return
		return success()
	}

	if err != nil {
		// the container has still not exited, and the kill function errored, so log the error here:
		logrus.WithError(err).WithField("container", container.ID).Errorf("Error sending stop (signal %d) to container", stopSignal)
	}
	if seconds < 0 {
		// if the client requested that we never kill / wait forever, but container.Wait was still
		// interrupted (parent context cancelled, for example), we should propagate the signal failure
		return err
	}

	logrus.WithField("container", container.ID).Infof("Container failed to exit within %s of signal %d - using the force", wait, stopSignal)
	// Stop either failed or container didnt exit, so fallback to kill.
	if err := daemon.Kill(container); err != nil {
		// got a kill error, but give container 2 more seconds to exit just in case
		subCtx, cancel := context.WithTimeout(ctx, 2*time.Second)
		defer cancel()
		if status := <-container.Wait(subCtx, containerpkg.WaitConditionNotRunning); status.Err() == nil {
			// container did exit, so ignore error and return
			return success()
		}
		logrus.WithError(err).WithField("container", container.ID).Error("Error killing the container")
		return err
	}

	return success()
}

package daemon // import "github.com/docker/docker/daemon"

import (
	"context"
	"time"

	containertypes "github.com/docker/docker/api/types/container"
	"github.com/docker/docker/container"
	"github.com/docker/docker/errdefs"
	"github.com/moby/sys/signal"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

// ContainerStop looks for the given container and stops it.
// In case the container fails to stop gracefully within a time duration
// specified by the timeout argument, in seconds, it is forcefully
// terminated (killed).
//
// If the timeout is nil, the container's StopTimeout value is used, if set,
// otherwise the engine default. A negative timeout value can be specified,
// meaning no timeout, i.e. no forceful termination is performed.
func (daemon *Daemon) ContainerStop(ctx context.Context, name string, options containertypes.StopOptions) error {
	ctr, err := daemon.GetContainer(name)
	if err != nil {
		return err
	}
	if !ctr.IsRunning() {
		return containerNotModifiedError{}
	}
	err = daemon.containerStop(ctx, ctr, options)
	if err != nil {
		return errdefs.System(errors.Wrapf(err, "cannot stop container: %s", name))
	}
	return nil
}

// containerStop sends a stop signal, waits, sends a kill signal.
func (daemon *Daemon) containerStop(ctx context.Context, ctr *container.Container, options containertypes.StopOptions) (retErr error) {
	if !ctr.IsRunning() {
		return nil
	}

	var (
		stopSignal  = ctr.StopSignal()
		stopTimeout = ctr.StopTimeout()
	)
	if options.Signal != "" {
		sig, err := signal.ParseSignal(options.Signal)
		if err != nil {
			return errdefs.InvalidParameter(err)
		}
		stopSignal = int(sig)
	}
	if options.Timeout != nil {
		stopTimeout = *options.Timeout
	}

	var wait time.Duration
	if stopTimeout >= 0 {
		wait = time.Duration(stopTimeout) * time.Second
	}
	defer func() {
		if retErr == nil {
			daemon.LogContainerEvent(ctr, "stop")
		}
	}()

	// 1. Send a stop signal
	err := daemon.killPossiblyDeadProcess(ctr, stopSignal)
	if err != nil {
		wait = 2 * time.Second
	}

	var subCtx context.Context
	var cancel context.CancelFunc
	if stopTimeout >= 0 {
		subCtx, cancel = context.WithTimeout(ctx, wait)
	} else {
		subCtx, cancel = context.WithCancel(ctx)
	}
	defer cancel()

	if status := <-ctr.Wait(subCtx, container.WaitConditionNotRunning); status.Err() == nil {
		// container did exit, so ignore any previous errors and return
		return nil
	}

	if err != nil {
		// the container has still not exited, and the kill function errored, so log the error here:
		logrus.WithError(err).WithField("container", ctr.ID).Errorf("Error sending stop (signal %d) to container", stopSignal)
	}
	if stopTimeout < 0 {
		// if the client requested that we never kill / wait forever, but container.Wait was still
		// interrupted (parent context cancelled, for example), we should propagate the signal failure
		return err
	}

	logrus.WithField("container", ctr.ID).Infof("Container failed to exit within %s of signal %d - using the force", wait, stopSignal)

	// Stop either failed or container didn't exit, so fallback to kill.
	if err := daemon.Kill(ctr); err != nil {
		// got a kill error, but give container 2 more seconds to exit just in case
		subCtx, cancel := context.WithTimeout(ctx, 2*time.Second)
		defer cancel()
		status := <-ctr.Wait(subCtx, container.WaitConditionNotRunning)
		if status.Err() != nil {
			logrus.WithError(err).WithField("container", ctr.ID).Errorf("error killing container: %v", status.Err())
			return err
		}
		// container did exit, so ignore previous errors and continue
	}

	return nil
}

Yes, you're right, I royally screwed up that comment 😂 

You can indeed use a local variable as long as you assign the error to handle in the defer to that local variable. In such cases, I tend to prefer the named return variable, as it's less easy to accidentally mask the local variable, which would happen if someone would change;

```go
err = errors.New("error")
return err
```

to

```go
return errors.New("error")
```

(of course the usually suspect would be; adding a `if err := something(); err != nil { return err}`)
