Skip to content

Commit f6473cc

Browse files
committed
Support all platform signal names
1 parent 24edab9 commit f6473cc

2 files changed

Lines changed: 84 additions & 9 deletions

File tree

internal/godemon/signals.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"strconv"
66
"strings"
77
"syscall"
8+
9+
"golang.org/x/sys/unix"
810
)
911

1012
const (
@@ -18,15 +20,13 @@ func parseSignal(name string) (syscall.Signal, error) {
1820
if err == nil {
1921
return syscall.Signal(n), nil
2022
}
21-
switch strings.TrimPrefix(strings.ToUpper(name), "SIG") {
22-
case "INT":
23-
return syscall.SIGINT, nil
24-
case "TERM":
25-
return syscall.SIGTERM, nil
26-
case "QUIT":
27-
return syscall.SIGQUIT, nil
28-
case "KILL":
29-
return syscall.SIGKILL, nil
23+
24+
signalName := strings.ToUpper(name)
25+
if !strings.HasPrefix(signalName, "SIG") {
26+
signalName = "SIG" + signalName
27+
}
28+
if signal := unix.SignalNum(signalName); signal != 0 {
29+
return signal, nil
3030
}
3131
return 0, fmt.Errorf("unsupported signal %q", name)
3232
}

internal/godemon/signals_test.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package godemon
2+
3+
import (
4+
"strconv"
5+
"strings"
6+
"syscall"
7+
"testing"
8+
9+
"golang.org/x/sys/unix"
10+
)
11+
12+
func TestParseSignalNameVariants(t *testing.T) {
13+
for _, testCase := range []struct {
14+
name string
15+
want syscall.Signal
16+
}{
17+
{name: "USR1", want: syscall.SIGUSR1},
18+
{name: "usr1", want: syscall.SIGUSR1},
19+
{name: "SIGUSR1", want: syscall.SIGUSR1},
20+
{name: "sigusr1", want: syscall.SIGUSR1},
21+
} {
22+
t.Run(testCase.name, func(t *testing.T) {
23+
got, err := parseSignal(testCase.name)
24+
if err != nil {
25+
t.Fatal(err)
26+
}
27+
if got != testCase.want {
28+
t.Fatalf("parseSignal(%q) = %d, want %d", testCase.name, got, testCase.want)
29+
}
30+
})
31+
}
32+
}
33+
34+
func TestParseSignalAcceptsEveryPlatformSignalName(t *testing.T) {
35+
for signal := syscall.Signal(1); signal < 256; signal++ {
36+
name := unix.SignalName(signal)
37+
if name == "" {
38+
continue
39+
}
40+
41+
for _, input := range []string{
42+
name,
43+
strings.ToLower(name),
44+
strings.TrimPrefix(name, "SIG"),
45+
} {
46+
got, err := parseSignal(input)
47+
if err != nil {
48+
t.Errorf("parseSignal(%q): %s", input, err)
49+
continue
50+
}
51+
if got != signal {
52+
t.Errorf("parseSignal(%q) = %d, want %d", input, got, signal)
53+
}
54+
}
55+
}
56+
}
57+
58+
func TestParseSignalPreservesNumericSignals(t *testing.T) {
59+
for _, signal := range []syscall.Signal{0, syscall.SIGUSR1, 255, -1} {
60+
name := strconv.Itoa(int(signal))
61+
got, err := parseSignal(name)
62+
if err != nil {
63+
t.Fatal(err)
64+
}
65+
if got != signal {
66+
t.Fatalf("parseSignal(%q) = %d, want %d", name, got, signal)
67+
}
68+
}
69+
}
70+
71+
func TestParseSignalRejectsUnknownName(t *testing.T) {
72+
if _, err := parseSignal("definitely-not-a-signal"); err == nil {
73+
t.Fatal("parseSignal accepted an unknown name")
74+
}
75+
}

0 commit comments

Comments
 (0)