mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: eliminate arbitrary timeouts in runBuiltTestProg and TestGdbBacktrace
This may fix the TestEINTR failures that have been frequent on the riscv64 builders since CL 445597. Updates #37405. Updates #39043. Change-Id: Iaf1403ff5ce2ff0203d5d0059908097d32d0b217 Reviewed-on: https://go-review.googlesource.com/c/go/+/447495 Auto-Submit: Bryan Mills <bcmills@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com> Run-TryBot: Bryan Mills <bcmills@google.com>
This commit is contained in:
parent
edfe078349
commit
0758a7d82d
2 changed files with 43 additions and 9 deletions
|
|
@ -6,7 +6,6 @@ package runtime_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
@ -66,15 +65,17 @@ func runBuiltTestProg(t *testing.T, exe, name string, env ...string) string {
|
||||||
t.Skip("-quick")
|
t.Skip("-quick")
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
start := time.Now()
|
||||||
defer cancel()
|
|
||||||
cmd := testenv.CleanCmdEnv(testenv.CommandContext(t, ctx, exe, name))
|
cmd := testenv.CleanCmdEnv(testenv.Command(t, exe, name))
|
||||||
cmd.Env = append(cmd.Env, env...)
|
cmd.Env = append(cmd.Env, env...)
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
cmd.Env = append(cmd.Env, "RUNTIME_TEST_SHORT=1")
|
cmd.Env = append(cmd.Env, "RUNTIME_TEST_SHORT=1")
|
||||||
}
|
}
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err == nil {
|
||||||
|
t.Logf("%v (%v): ok", cmd, time.Since(start))
|
||||||
|
} else {
|
||||||
if _, ok := err.(*exec.ExitError); ok {
|
if _, ok := err.(*exec.ExitError); ok {
|
||||||
t.Logf("%v: %v", cmd, err)
|
t.Logf("%v: %v", cmd, err)
|
||||||
} else if errors.Is(err, exec.ErrWaitDelay) {
|
} else if errors.Is(err, exec.ErrWaitDelay) {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ package runtime_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"internal/testenv"
|
"internal/testenv"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -400,6 +400,15 @@ func TestGdbBacktrace(t *testing.T) {
|
||||||
if runtime.GOOS == "netbsd" {
|
if runtime.GOOS == "netbsd" {
|
||||||
testenv.SkipFlaky(t, 15603)
|
testenv.SkipFlaky(t, 15603)
|
||||||
}
|
}
|
||||||
|
if flag.Lookup("test.parallel").Value.(flag.Getter).Get().(int) < 2 {
|
||||||
|
// It is possible that this test will hang for a long time due to an
|
||||||
|
// apparent GDB bug reported in https://go.dev/issue/37405.
|
||||||
|
// If test parallelism is high enough, that might be ok: the other parallel
|
||||||
|
// tests will finish, and then this test will finish right before it would
|
||||||
|
// time out. However, if test are running sequentially, a hang in this test
|
||||||
|
// would likely cause the remaining tests to run out of time.
|
||||||
|
testenv.SkipFlaky(t, 37405)
|
||||||
|
}
|
||||||
|
|
||||||
checkGdbEnvironment(t)
|
checkGdbEnvironment(t)
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
@ -421,6 +430,7 @@ func TestGdbBacktrace(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute gdb commands.
|
// Execute gdb commands.
|
||||||
|
start := time.Now()
|
||||||
args := []string{"-nx", "-batch",
|
args := []string{"-nx", "-batch",
|
||||||
"-iex", "add-auto-load-safe-path " + filepath.Join(testenv.GOROOT(t), "src", "runtime"),
|
"-iex", "add-auto-load-safe-path " + filepath.Join(testenv.GOROOT(t), "src", "runtime"),
|
||||||
"-ex", "set startup-with-shell off",
|
"-ex", "set startup-with-shell off",
|
||||||
|
|
@ -430,9 +440,32 @@ func TestGdbBacktrace(t *testing.T) {
|
||||||
"-ex", "continue",
|
"-ex", "continue",
|
||||||
filepath.Join(dir, "a.exe"),
|
filepath.Join(dir, "a.exe"),
|
||||||
}
|
}
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
cmd = testenv.Command(t, "gdb", args...)
|
||||||
defer cancel()
|
|
||||||
got, err := testenv.CommandContext(t, ctx, "gdb", args...).CombinedOutput()
|
// Work around the GDB hang reported in https://go.dev/issue/37405.
|
||||||
|
// Sometimes (rarely), the GDB process hangs completely when the Go program
|
||||||
|
// exits, and we suspect that the bug is on the GDB side.
|
||||||
|
//
|
||||||
|
// The default Cancel function added by testenv.Command will mark the test as
|
||||||
|
// failed if it is in danger of timing out, but we want to instead mark it as
|
||||||
|
// skipped. Change the Cancel function to kill the process and merely log
|
||||||
|
// instead of failing the test.
|
||||||
|
//
|
||||||
|
// (This approach does not scale: if the test parallelism is less than or
|
||||||
|
// equal to the number of tests that run right up to the deadline, then the
|
||||||
|
// remaining parallel tests are likely to time out. But as long as it's just
|
||||||
|
// this one flaky test, it's probably fine..?)
|
||||||
|
//
|
||||||
|
// If there is no deadline set on the test at all, relying on the timeout set
|
||||||
|
// by testenv.Command will cause the test to hang indefinitely, but that's
|
||||||
|
// what “no deadline” means, after all — and it's probably the right behavior
|
||||||
|
// anyway if someone is trying to investigate and fix the GDB bug.
|
||||||
|
cmd.Cancel = func() error {
|
||||||
|
t.Logf("GDB command timed out after %v: %v", time.Since(start), cmd)
|
||||||
|
return cmd.Process.Kill()
|
||||||
|
}
|
||||||
|
|
||||||
|
got, err := cmd.CombinedOutput()
|
||||||
t.Logf("gdb output:\n%s", got)
|
t.Logf("gdb output:\n%s", got)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if bytes.Contains(got, []byte("internal-error: wait returned unexpected status 0x0")) {
|
if bytes.Contains(got, []byte("internal-error: wait returned unexpected status 0x0")) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue