diff --git a/pkg/signal/signal.go b/pkg/signal/signal.go index 88ef7b5ea2..bbe006bd0b 100644 --- a/pkg/signal/signal.go +++ b/pkg/signal/signal.go @@ -12,9 +12,16 @@ import ( ) // CatchAll catches all signals and relays them to the specified channel. +// On Linux, SIGURG is not handled, as it's used by the Go runtime to support +// preemptable system calls. func CatchAll(sigc chan os.Signal) { var handledSigs []os.Signal for _, s := range SignalMap { + if isRuntimeSig(s) { + // Do not handle SIGURG on Linux, as in go1.14+, the go runtime issues + // SIGURG as an interrupt to support preemptable system calls on Linux. + continue + } handledSigs = append(handledSigs, s) } signal.Notify(sigc, handledSigs...) diff --git a/pkg/signal/signal_darwin.go b/pkg/signal/signal_darwin.go index ee5501e3d9..8ffd3d73d3 100644 --- a/pkg/signal/signal_darwin.go +++ b/pkg/signal/signal_darwin.go @@ -1,6 +1,7 @@ package signal // import "github.com/docker/docker/pkg/signal" import ( + "os" "syscall" ) @@ -39,3 +40,7 @@ var SignalMap = map[string]syscall.Signal{ "XCPU": syscall.SIGXCPU, "XFSZ": syscall.SIGXFSZ, } + +func isRuntimeSig(_ os.Signal) bool { + return false +} diff --git a/pkg/signal/signal_freebsd.go b/pkg/signal/signal_freebsd.go index 764f90e264..a5e774a538 100644 --- a/pkg/signal/signal_freebsd.go +++ b/pkg/signal/signal_freebsd.go @@ -1,6 +1,7 @@ package signal // import "github.com/docker/docker/pkg/signal" import ( + "os" "syscall" ) @@ -41,3 +42,7 @@ var SignalMap = map[string]syscall.Signal{ "XCPU": syscall.SIGXCPU, "XFSZ": syscall.SIGXFSZ, } + +func isRuntimeSig(_ os.Signal) bool { + return false +} diff --git a/pkg/signal/signal_linux.go b/pkg/signal/signal_linux.go index 4013bded13..46fe6bbad0 100644 --- a/pkg/signal/signal_linux.go +++ b/pkg/signal/signal_linux.go @@ -3,6 +3,7 @@ package signal // import "github.com/docker/docker/pkg/signal" import ( + "os" "syscall" "golang.org/x/sys/unix" @@ -81,3 +82,7 @@ var SignalMap = map[string]syscall.Signal{ "RTMAX-1": sigrtmax - 1, "RTMAX": sigrtmax, } + +func isRuntimeSig(s os.Signal) bool { + return s == unix.SIGURG +} diff --git a/pkg/signal/signal_linux_mipsx.go b/pkg/signal/signal_linux_mipsx.go index c78c887af5..665d849adb 100644 --- a/pkg/signal/signal_linux_mipsx.go +++ b/pkg/signal/signal_linux_mipsx.go @@ -4,6 +4,7 @@ package signal // import "github.com/docker/docker/pkg/signal" import ( + "os" "syscall" "golang.org/x/sys/unix" @@ -82,3 +83,7 @@ var SignalMap = map[string]syscall.Signal{ "RTMAX-1": sigrtmax - 1, "RTMAX": sigrtmax, } + +func isRuntimeSig(s os.Signal) bool { + return s == unix.SIGURG +} diff --git a/pkg/signal/signal_linux_test.go b/pkg/signal/signal_linux_test.go index 8e2fb98dbb..decd454de3 100644 --- a/pkg/signal/signal_linux_test.go +++ b/pkg/signal/signal_linux_test.go @@ -6,6 +6,7 @@ import ( "os" "syscall" "testing" + "time" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" @@ -34,6 +35,22 @@ func TestCatchAll(t *testing.T) { } } +func TestCatchAllIgnoreSigUrg(t *testing.T) { + sigs := make(chan os.Signal, 1) + CatchAll(sigs) + defer StopCatch(sigs) + + err := syscall.Kill(syscall.Getpid(), syscall.SIGURG) + assert.NilError(t, err) + timer := time.NewTimer(1 * time.Second) + defer timer.Stop() + select { + case <-timer.C: + case s := <-sigs: + t.Fatalf("expected no signals to be handled, but received %q", s.String()) + } +} + func TestStopCatch(t *testing.T) { signal := SignalMap["HUP"] channel := make(chan os.Signal, 1) diff --git a/pkg/signal/signal_windows.go b/pkg/signal/signal_windows.go index 65752f24aa..d44662c4e4 100644 --- a/pkg/signal/signal_windows.go +++ b/pkg/signal/signal_windows.go @@ -1,6 +1,7 @@ package signal // import "github.com/docker/docker/pkg/signal" import ( + "os" "syscall" ) @@ -24,3 +25,7 @@ var SignalMap = map[string]syscall.Signal{ "KILL": syscall.SIGKILL, "TERM": syscall.SIGTERM, } + +func isRuntimeSig(_ os.Signal) bool { + return false +}