pkg/signal.CatchAll: ignore SIGURG on Linux

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.

This issue was caught in TestCatchAll, which could fail when updating to Go 1.14 or above;

    === Failed
    === FAIL: pkg/signal TestCatchAll (0.01s)
        signal_linux_test.go:32: assertion failed: urgent I/O condition (string) != continued (string)
        signal_linux_test.go:32: assertion failed: continued (string) != hangup (string)
        signal_linux_test.go:32: assertion failed: hangup (string) != child exited (string)
        signal_linux_test.go:32: assertion failed: child exited (string) != illegal instruction (string)
        signal_linux_test.go:32: assertion failed: illegal instruction (string) != floating point exception (string)

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit b7ebf32ba3)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2021-05-19 19:42:18 +02:00
parent a23a880c6e
commit 41cf01fa93
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
7 changed files with 49 additions and 0 deletions

View File

@ -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...)

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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)

View File

@ -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
}