Files
moby/cmd/dockerd/trap/trap_linux_test.go
Cory Snider 0867d3173c cmd/dockerd: use default SIGQUIT behaviour
dockerd handles SIGQUIT by dumping all goroutine stacks to standard
error and exiting. In contrast, the Go runtime's default SIGQUIT
behaviour... dumps all goroutine stacks to standard error and exits.
The default SIGQUIT behaviour is implemented directly in the runtime's
signal handler, and so is both more robust to bugs in the Go runtime and
does not perturb the state of the process to anywhere near same degree
as dumping goroutine stacks from a user goroutine. The only notable
difference from a user's perspective is that the process exits with
status 2 instead of 128+SIGQUIT.

Signed-off-by: Cory Snider <csnider@mirantis.com>
2023-01-10 17:11:54 -05:00

65 lines
1.5 KiB
Go

//go:build linux
// +build linux
package trap // import "github.com/docker/docker/cmd/dockerd/trap"
import (
"os"
"os/exec"
"syscall"
"testing"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
)
func buildTestBinary(t *testing.T, tmpdir string, prefix string) (string, string) {
t.Helper()
tmpDir, err := os.MkdirTemp(tmpdir, prefix)
assert.NilError(t, err)
exePath := tmpDir + "/" + prefix
wd, _ := os.Getwd()
testHelperCode := wd + "/testfiles/main.go"
cmd := exec.Command("go", "build", "-o", exePath, testHelperCode)
err = cmd.Run()
assert.NilError(t, err)
return exePath, tmpDir
}
func TestTrap(t *testing.T) {
var sigmap = []struct {
name string
signal os.Signal
multiple bool
}{
{"TERM", syscall.SIGTERM, false},
{"INT", os.Interrupt, false},
{"TERM", syscall.SIGTERM, true},
{"INT", os.Interrupt, true},
}
exePath, tmpDir := buildTestBinary(t, "", "main")
defer os.RemoveAll(tmpDir)
for _, v := range sigmap {
t.Run(v.name, func(t *testing.T) {
cmd := exec.Command(exePath)
cmd.Env = append(os.Environ(), "SIGNAL_TYPE="+v.name)
if v.multiple {
cmd.Env = append(cmd.Env, "IF_MULTIPLE=1")
}
err := cmd.Start()
assert.NilError(t, err)
err = cmd.Wait()
e, ok := err.(*exec.ExitError)
assert.Assert(t, ok, "expected exec.ExitError, got %T", e)
code := e.Sys().(syscall.WaitStatus).ExitStatus()
if v.multiple {
assert.Check(t, is.DeepEqual(128+int(v.signal.(syscall.Signal)), code))
} else {
assert.Check(t, is.Equal(99, code))
}
})
}
}