1
0
mirror of https://github.com/golang/go synced 2024-11-18 22:44:48 -07:00

os: use testenv.Command and os.Executable in tests

On Unix platforms, testenv.Command sends SIGQUIT to stuck commands
before the test times out. For subprocesses that are written in Go,
that causes the runtime to dump running goroutines, and in other
languages it triggers similar behavior (such as a core dump).
If the subprocess is stuck due to a bug (such as #57999), that may
help to diagnose it.

For #57999.

Change-Id: I00f381b8052cbbb1a7eea90e7f102a3f68c842d1
Reviewed-on: https://go-review.googlesource.com/c/go/+/521817
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Bryan Mills <bcmills@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Auto-Submit: Bryan Mills <bcmills@google.com>
This commit is contained in:
Bryan C. Mills 2023-08-22 11:32:20 -04:00 committed by Gopher Robot
parent f92741b1d8
commit 738d2d9068
2 changed files with 36 additions and 11 deletions

View File

@ -14,9 +14,9 @@ import (
"context"
"encoding/binary"
"fmt"
"internal/testenv"
"internal/testpty"
"os"
"os/exec"
"os/signal"
"runtime"
"strconv"
@ -93,7 +93,7 @@ func TestTerminalSignal(t *testing.T) {
// Main test process, run code below.
break
case "1":
runSessionLeader(pause)
runSessionLeader(t, pause)
panic("unreachable")
case "2":
runStoppingChild()
@ -128,9 +128,22 @@ func TestTerminalSignal(t *testing.T) {
t.Fatal(err)
}
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Second)
defer cancel()
cmd := exec.CommandContext(ctx, os.Args[0], "-test.run=TestTerminalSignal")
var (
ctx = context.Background()
cmdArgs = []string{"-test.run=TestTerminalSignal"}
)
if deadline, ok := t.Deadline(); ok {
d := time.Until(deadline)
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, d)
t.Cleanup(cancel)
// We run the subprocess with an additional 20% margin to allow it to fail
// and clean up gracefully if it times out.
cmdArgs = append(cmdArgs, fmt.Sprintf("-test.timeout=%v", d*5/4))
}
cmd := testenv.CommandContext(t, ctx, os.Args[0], cmdArgs...)
cmd.Env = append(os.Environ(), "GO_TEST_TERMINAL_SIGNALS=1")
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout // for logging
@ -216,7 +229,7 @@ func TestTerminalSignal(t *testing.T) {
}
// GO_TEST_TERMINAL_SIGNALS=1 subprocess above.
func runSessionLeader(pause time.Duration) {
func runSessionLeader(t *testing.T, pause time.Duration) {
// "Attempts to use tcsetpgrp() from a process which is a
// member of a background process group on a fildes associated
// with its controlling terminal shall cause the process group
@ -235,10 +248,22 @@ func runSessionLeader(pause time.Duration) {
pty := os.NewFile(ptyFD, "pty")
controlW := os.NewFile(controlFD, "control-pipe")
// Slightly shorter timeout than in the parent.
ctx, cancel := context.WithTimeout(context.Background(), 90*time.Second)
defer cancel()
cmd := exec.CommandContext(ctx, os.Args[0], "-test.run=TestTerminalSignal")
var (
ctx = context.Background()
cmdArgs = []string{"-test.run=TestTerminalSignal"}
)
if deadline, ok := t.Deadline(); ok {
d := time.Until(deadline)
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, d)
t.Cleanup(cancel)
// We run the subprocess with an additional 20% margin to allow it to fail
// and clean up gracefully if it times out.
cmdArgs = append(cmdArgs, fmt.Sprintf("-test.timeout=%v", d*5/4))
}
cmd := testenv.CommandContext(t, ctx, os.Args[0], cmdArgs...)
cmd.Env = append(os.Environ(), "GO_TEST_TERMINAL_SIGNALS=2")
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout

View File

@ -483,7 +483,7 @@ func TestNohup(t *testing.T) {
defer wg.Done()
// POSIX specifies that nohup writes to a file named nohup.out if standard
// output is a terminal. However, for an exec.Command, standard output is
// output is a terminal. However, for an exec.Cmd, standard output is
// not a terminal — so we don't need to read or remove that file (and,
// indeed, cannot even create it if the current user is unable to write to
// GOROOT/src, such as when GOROOT is installed and owned by root).