Source file
src/syscall/exec_pdeathsig_test.go
1
2
3
4
5
6
7 package syscall_test
8
9 import (
10 "bufio"
11 "fmt"
12 "io"
13 "os"
14 "os/exec"
15 "os/signal"
16 "path/filepath"
17 "syscall"
18 "testing"
19 "time"
20 )
21
22 func TestDeathSignal(t *testing.T) {
23 if os.Getuid() != 0 {
24 t.Skip("skipping root only test")
25 }
26
27
28
29 tempDir, err := os.MkdirTemp("", "TestDeathSignal")
30 if err != nil {
31 t.Fatalf("cannot create temporary directory: %v", err)
32 }
33 defer os.RemoveAll(tempDir)
34 os.Chmod(tempDir, 0755)
35
36 tmpBinary := filepath.Join(tempDir, filepath.Base(os.Args[0]))
37
38 src, err := os.Open(os.Args[0])
39 if err != nil {
40 t.Fatalf("cannot open binary %q, %v", os.Args[0], err)
41 }
42 defer src.Close()
43
44 dst, err := os.OpenFile(tmpBinary, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
45 if err != nil {
46 t.Fatalf("cannot create temporary binary %q, %v", tmpBinary, err)
47 }
48 if _, err := io.Copy(dst, src); err != nil {
49 t.Fatalf("failed to copy test binary to %q, %v", tmpBinary, err)
50 }
51 err = dst.Close()
52 if err != nil {
53 t.Fatalf("failed to close test binary %q, %v", tmpBinary, err)
54 }
55
56 cmd := exec.Command(tmpBinary)
57 cmd.Env = append(os.Environ(), "GO_DEATHSIG_PARENT=1")
58 chldStdin, err := cmd.StdinPipe()
59 if err != nil {
60 t.Fatalf("failed to create new stdin pipe: %v", err)
61 }
62 chldStdout, err := cmd.StdoutPipe()
63 if err != nil {
64 t.Fatalf("failed to create new stdout pipe: %v", err)
65 }
66 cmd.Stderr = os.Stderr
67
68 err = cmd.Start()
69 defer cmd.Wait()
70 if err != nil {
71 t.Fatalf("failed to start first child process: %v", err)
72 }
73
74 chldPipe := bufio.NewReader(chldStdout)
75
76 if got, err := chldPipe.ReadString('\n'); got == "start\n" {
77 syscall.Kill(cmd.Process.Pid, syscall.SIGTERM)
78
79 go func() {
80 time.Sleep(5 * time.Second)
81 chldStdin.Close()
82 }()
83
84 want := "ok\n"
85 if got, err = chldPipe.ReadString('\n'); got != want {
86 t.Fatalf("expected %q, received %q, %v", want, got, err)
87 }
88 } else {
89 t.Fatalf("did not receive start from child, received %q, %v", got, err)
90 }
91 }
92
93 func deathSignalParent() {
94 cmd := exec.Command(os.Args[0])
95 cmd.Env = append(os.Environ(),
96 "GO_DEATHSIG_PARENT=",
97 "GO_DEATHSIG_CHILD=1",
98 )
99 cmd.Stdin = os.Stdin
100 cmd.Stdout = os.Stdout
101 attrs := syscall.SysProcAttr{
102 Pdeathsig: syscall.SIGUSR1,
103
104
105 Credential: &syscall.Credential{Uid: 99, Gid: 99},
106 }
107 cmd.SysProcAttr = &attrs
108
109 err := cmd.Start()
110 if err != nil {
111 fmt.Fprintf(os.Stderr, "death signal parent error: %v\n", err)
112 os.Exit(1)
113 }
114 cmd.Wait()
115 os.Exit(0)
116 }
117
118 func deathSignalChild() {
119 c := make(chan os.Signal, 1)
120 signal.Notify(c, syscall.SIGUSR1)
121 go func() {
122 <-c
123 fmt.Println("ok")
124 os.Exit(0)
125 }()
126 fmt.Println("start")
127
128 buf := make([]byte, 32)
129 os.Stdin.Read(buf)
130
131
132 fmt.Println("not ok")
133 os.Exit(1)
134 }
135
View as plain text