container: Container.StopSignal: fix handling of invalid signals

Commit 0e50d946a2 introduced a feature to
allow a custom stop-signal to be set. As part of this, existing code to
parse the signal was extracted to `signal.ParseSignal()`, which accepts
a string either containing a numeric value or a named signal.

When failing to parse the given signal, it returns an error and a magic
"-1" signal. The changes in 0e50d946a2 used
the error when creating a container, but for existing container configs,
it would ignore the error and instead check if the signal was "0", in
which case it would fall back to use the default stop-signal (SIGTERM).

Given that  `signal.ParseSignal()` returns "-1" (not "0") for invalid
signals, this would result in the failure going undetected and "-1"
being used instead of the intended default (SIGTERM).

In practice, this issues would unlikely be encountered, as custom signals
are validated when creating the container, but it would be possible for
an image to contain an invalid signal, which would be used by the container
as default.

This patch updates the logic to only use the custom value if no error is
produced and a non-zero, positive signal is returned.

A test-case was added that would fail before this patch:

    go test -v -run TestContainerStopSignal
    === RUN   TestContainerStopSignal
        container_test.go:34: assertion failed: signal -1 (s syscall.Signal) != terminated (defaultStopSignal syscall.Signal)
    --- FAIL: TestContainerStopSignal (0.00s)

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn
2025-02-15 18:55:03 +01:00
parent ef0fe1ac00
commit 529a56d31a
2 changed files with 12 additions and 6 deletions

View File

@@ -581,13 +581,13 @@ func (container *Container) IsDestinationMounted(destination string) bool {
// StopSignal returns the signal used to stop the container.
func (container *Container) StopSignal() syscall.Signal {
var stopSignal syscall.Signal
stopSignal := defaultStopSignal
if container.Config.StopSignal != "" {
stopSignal, _ = signal.ParseSignal(container.Config.StopSignal)
}
if stopSignal == 0 {
stopSignal = defaultStopSignal
// signal.ParseSignal returns "-1" for invalid or unknown signals.
sig, err := signal.ParseSignal(container.Config.StopSignal)
if err == nil && sig > 0 {
stopSignal = sig
}
}
return stopSignal
}

View File

@@ -26,6 +26,12 @@ func TestContainerStopSignal(t *testing.T) {
s = c.StopSignal()
expected := syscall.SIGKILL
assert.Equal(t, s, expected)
c = &Container{
Config: &container.Config{StopSignal: "NOSUCHSIGNAL"},
}
s = c.StopSignal()
assert.Equal(t, s, defaultStopSignal)
}
func TestContainerStopTimeout(t *testing.T) {