Skip to content

Commit 47fe143

Browse files
committed
Test for signal forwarding
Signed-off-by: Michael Dwan <[email protected]>
1 parent a310cc2 commit 47fe143

File tree

2 files changed

+120
-0
lines changed

2 files changed

+120
-0
lines changed

machine_test.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"net"
2424
"os"
2525
"os/exec"
26+
"os/signal"
2627
"path/filepath"
2728
"strconv"
2829
"strings"
@@ -1199,3 +1200,106 @@ func createValidConfig(t *testing.T, socketPath string) Config {
11991200
},
12001201
}
12011202
}
1203+
1204+
func TestSignalForwarding(t *testing.T) {
1205+
forwardedSignals := []os.Signal{
1206+
syscall.SIGUSR1,
1207+
syscall.SIGUSR2,
1208+
syscall.SIGINT,
1209+
syscall.SIGTERM,
1210+
}
1211+
ignoredSignals := []os.Signal{
1212+
syscall.SIGHUP,
1213+
syscall.SIGQUIT,
1214+
}
1215+
1216+
cfg := Config{
1217+
Debug: true,
1218+
KernelImagePath: filepath.Join(testDataPath, "vmlinux"),
1219+
SocketPath: "/tmp/TestSignalForwarding.sock",
1220+
Drives: []models.Drive{
1221+
{
1222+
DriveID: String("0"),
1223+
IsRootDevice: Bool(true),
1224+
IsReadOnly: Bool(false),
1225+
PathOnHost: String(testRootfs),
1226+
},
1227+
},
1228+
DisableValidation: true,
1229+
ForwardSignals: forwardedSignals,
1230+
}
1231+
defer os.RemoveAll("/tmp/TestSignalForwarding.sock")
1232+
1233+
opClient := fctesting.MockClient{}
1234+
1235+
ctx := context.Background()
1236+
client := NewClient(cfg.SocketPath, fctesting.NewLogEntry(t), true, WithOpsClient(&opClient))
1237+
1238+
fd, err := net.Listen("unix", cfg.SocketPath)
1239+
if err != nil {
1240+
t.Fatalf("unexpected error during creation of unix socket: %v", err)
1241+
}
1242+
defer fd.Close()
1243+
1244+
stdout := &bytes.Buffer{}
1245+
stderr := &bytes.Buffer{}
1246+
cmd := exec.Command(filepath.Join(testDataPath, "sigprint.sh"))
1247+
cmd.Stdout = stdout
1248+
cmd.Stderr = stderr
1249+
stdin, err := cmd.StdinPipe()
1250+
assert.NoError(t, err)
1251+
1252+
m, err := NewMachine(
1253+
ctx,
1254+
cfg,
1255+
WithClient(client),
1256+
WithProcessRunner(cmd),
1257+
WithLogger(fctesting.NewLogEntry(t)),
1258+
)
1259+
if err != nil {
1260+
t.Fatalf("failed to create new machine: %v", err)
1261+
}
1262+
1263+
if err := m.startVMM(ctx); err != nil {
1264+
t.Fatalf("error startVMM: %v", err)
1265+
}
1266+
defer m.StopVMM()
1267+
1268+
sigChan := make(chan os.Signal)
1269+
signal.Notify(sigChan, ignoredSignals...)
1270+
defer func() {
1271+
signal.Stop(sigChan)
1272+
close(sigChan)
1273+
}()
1274+
1275+
go func() {
1276+
for sig := range sigChan {
1277+
t.Logf("received signal %v, ignoring", sig)
1278+
}
1279+
}()
1280+
1281+
go func() {
1282+
for _, sig := range append(forwardedSignals, ignoredSignals...) {
1283+
t.Logf("sending signal %v to self", sig)
1284+
syscall.Kill(syscall.Getpid(), sig.(syscall.Signal))
1285+
}
1286+
1287+
// give the child process time to receive signals and flush pipes
1288+
time.Sleep(1 * time.Second)
1289+
1290+
// terminate the signal printing process
1291+
stdin.Write([]byte("q"))
1292+
}()
1293+
1294+
err = m.Wait(ctx)
1295+
require.NoError(t, err, "wait returned an error")
1296+
1297+
receivedSignals := []os.Signal{}
1298+
for _, sigStr := range strings.Split(strings.TrimSpace(stdout.String()), "\n") {
1299+
i, err := strconv.Atoi(sigStr)
1300+
require.NoError(t, err, "expected numeric output")
1301+
receivedSignals = append(receivedSignals, syscall.Signal(i))
1302+
}
1303+
1304+
assert.ElementsMatch(t, forwardedSignals, receivedSignals)
1305+
}

testdata/sigprint.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/bin/bash
2+
3+
typeset -i sig=1
4+
while (( sig < 65 )); do
5+
trap "echo '$sig'" $sig 2>/dev/null
6+
let sig=sig+1
7+
done
8+
9+
>&2 echo "Send signals to PID $$ and type [q] when done."
10+
11+
while :
12+
do
13+
read -n1 input
14+
[ "$input" == "q" ] && break
15+
sleep .1
16+
done

0 commit comments

Comments
 (0)