cmd/tailscaled, tstest/integration: make tailscaled die when parent dies

I noticed that failed tests were leaving aroudn stray tailscaled processes
on macOS at least.

To repro, add this to tstest/integration:

    func TestFailInFewSeconds(t *testing.T) {
        t.Parallel()
        time.Sleep(3 * time.Second)
        os.Exit(1)
        t.Fatal("boom")
    }

Those three seconds let the other parallel tests (with all their
tailscaled child processes) start up and start running their tests,
but then we violently os.Exit(1) the test driver and all the children
were kept alive (and were spinning away, using all available CPU in
gvisor scheduler code, which is a separate scary issue)

Updates #cleanup

Change-Id: I9c891ed1a1ec639fb2afec2808c04dbb8a460e0e
Co-authored-by: Maisem Ali <maisem@tailscale.com>
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick 2023-09-01 12:19:54 -07:00 committed by Brad Fitzpatrick
parent e1fbb5457b
commit 055fdb235f
2 changed files with 24 additions and 0 deletions

View File

@ -202,6 +202,10 @@ func main() {
}
}
if fd, ok := envknob.LookupInt("TS_PARENT_DEATH_FD"); ok && fd > 2 {
go dieOnPipeReadErrorOfFD(fd)
}
if printVersion {
fmt.Println(version.String())
os.Exit(0)
@ -769,3 +773,14 @@ func beChild(args []string) error {
}
return f(args[1:])
}
// dieOnPipeReadErrorOfFD reads from the pipe named by fd and exit the process
// when the pipe becomes readable. We use this in tests as a somewhat more
// portable mechanism for the Linux PR_SET_PDEATHSIG, which we wish existed on
// macOS. This helps us clean up straggler tailscaled processes when the parent
// test driver dies unexpectedly.
func dieOnPipeReadErrorOfFD(fd int) {
f := os.NewFile(uintptr(fd), "TS_PARENT_DEATH_FD")
f.Read(make([]byte, 1))
os.Exit(1)
}

View File

@ -934,6 +934,15 @@ func (n *testNode) StartDaemonAsIPNGOOS(ipnGOOS string) *Daemon {
cmd.Stdout = os.Stdout
cmd.Stderr = io.MultiWriter(cmd.Stderr, os.Stderr)
}
if runtime.GOOS != "windows" {
pr, pw, err := os.Pipe()
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { pw.Close() })
cmd.ExtraFiles = append(cmd.ExtraFiles, pr)
cmd.Env = append(cmd.Env, "TS_PARENT_DEATH_FD=3")
}
if err := cmd.Start(); err != nil {
t.Fatalf("starting tailscaled: %v", err)
}