1 // Copyright 2015 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
21 func TestMain(m
*testing
.M
) {
22 if os
.Getenv("GO_DEATHSIG_PARENT") == "1" {
24 } else if os
.Getenv("GO_DEATHSIG_CHILD") == "1" {
31 func TestLinuxDeathSignal(t
*testing
.T
) {
33 t
.Skip("skipping root only test")
36 // Copy the test binary to a location that a non-root user can read/execute
37 // after we drop privileges
38 tempDir
, err
:= ioutil
.TempDir("", "TestDeathSignal")
40 t
.Fatalf("cannot create temporary directory: %v", err
)
42 defer os
.RemoveAll(tempDir
)
43 os
.Chmod(tempDir
, 0755)
45 tmpBinary
:= filepath
.Join(tempDir
, filepath
.Base(os
.Args
[0]))
47 src
, err
:= os
.Open(os
.Args
[0])
49 t
.Fatalf("cannot open binary %q, %v", os
.Args
[0], err
)
53 dst
, err
:= os
.OpenFile(tmpBinary
, os
.O_WRONLY|os
.O_CREATE|os
.O_TRUNC
, 0755)
55 t
.Fatalf("cannot create temporary binary %q, %v", tmpBinary
, err
)
57 if _
, err
:= io
.Copy(dst
, src
); err
!= nil {
58 t
.Fatalf("failed to copy test binary to %q, %v", tmpBinary
, err
)
62 t
.Fatalf("failed to close test binary %q, %v", tmpBinary
, err
)
65 cmd
:= exec
.Command(tmpBinary
)
66 cmd
.Env
= []string{"GO_DEATHSIG_PARENT=1"}
67 chldStdin
, err
:= cmd
.StdinPipe()
69 t
.Fatalf("failed to create new stdin pipe: %v", err
)
71 chldStdout
, err
:= cmd
.StdoutPipe()
73 t
.Fatalf("failed to create new stdout pipe: %v", err
)
75 cmd
.Stderr
= os
.Stderr
80 t
.Fatalf("failed to start first child process: %v", err
)
83 chldPipe
:= bufio
.NewReader(chldStdout
)
85 if got
, err
:= chldPipe
.ReadString('\n'); got
== "start\n" {
86 syscall
.Kill(cmd
.Process
.Pid
, syscall
.SIGTERM
)
89 time
.Sleep(5 * time
.Second
)
94 if got
, err
= chldPipe
.ReadString('\n'); got
!= want
{
95 t
.Fatalf("expected %q, received %q, %v", want
, got
, err
)
98 t
.Fatalf("did not receive start from child, received %q, %v", got
, err
)
102 func deathSignalParent() {
103 cmd
:= exec
.Command(os
.Args
[0])
104 cmd
.Env
= []string{"GO_DEATHSIG_CHILD=1"}
106 cmd
.Stdout
= os
.Stdout
107 attrs
:= syscall
.SysProcAttr
{
108 Pdeathsig
: syscall
.SIGUSR1
,
109 // UID/GID 99 is the user/group "nobody" on RHEL/Fedora and is
111 Credential
: &syscall
.Credential
{Uid
: 99, Gid
: 99},
113 cmd
.SysProcAttr
= &attrs
117 fmt
.Fprintf(os
.Stderr
, "death signal parent error: %v\n", err
)
124 func deathSignalChild() {
125 c
:= make(chan os
.Signal
, 1)
126 signal
.Notify(c
, syscall
.SIGUSR1
)
134 buf
:= make([]byte, 32)
137 // We expected to be signaled before stdin closed
138 fmt
.Println("not ok")