diff options
author | Ian Lance Taylor <iant@golang.org> | 2016-06-14 14:38:22 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2016-06-15 15:03:48 +0000 |
commit | 26d6dc6bf8a7e5487844a63aa26a4de3afdd688e (patch) | |
tree | 48d0f94e0fcb8e330c50a1732788736a5c4ddc90 | |
parent | 48cc3c4b587f9549f7426776d032da99b3ba471b (diff) | |
download | go-26d6dc6bf8a7e5487844a63aa26a4de3afdd688e.tar.gz go-26d6dc6bf8a7e5487844a63aa26a4de3afdd688e.zip |
runtime: if the test program hangs, try to get a stack trace
This is an attempt to get more information for #14809, which seems to
occur rarely.
Updates #14809.
Change-Id: Idbeb136ceb57993644e03266622eb699d2685d02
Reviewed-on: https://go-review.googlesource.com/24110
Reviewed-by: Mikio Hara <mikioh.mikioh@gmail.com>
Reviewed-by: Austin Clements <austin@google.com>
-rw-r--r-- | src/runtime/crash_nonunix_test.go | 13 | ||||
-rw-r--r-- | src/runtime/crash_test.go | 44 | ||||
-rw-r--r-- | src/runtime/crash_unix_test.go | 4 |
3 files changed, 59 insertions, 2 deletions
diff --git a/src/runtime/crash_nonunix_test.go b/src/runtime/crash_nonunix_test.go new file mode 100644 index 0000000000..2ce995c069 --- /dev/null +++ b/src/runtime/crash_nonunix_test.go @@ -0,0 +1,13 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build windows plan9 nacl + +package runtime_test + +import "os" + +// sigquit is the signal to send to kill a hanging testdata program. +// On Unix we send SIGQUIT, but on non-Unix we only have os.Kill. +var sigquit = os.Kill diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go index ec740990dc..0b4a1f538a 100644 --- a/src/runtime/crash_test.go +++ b/src/runtime/crash_test.go @@ -5,6 +5,7 @@ package runtime_test import ( + "bytes" "fmt" "internal/testenv" "io/ioutil" @@ -13,9 +14,11 @@ import ( "path/filepath" "regexp" "runtime" + "strconv" "strings" "sync" "testing" + "time" ) var toRemove []string @@ -65,8 +68,45 @@ func runTestProg(t *testing.T, binary, name string) string { if err != nil { t.Fatal(err) } - got, _ := testEnv(exec.Command(exe, name)).CombinedOutput() - return string(got) + + cmd := testEnv(exec.Command(exe, name)) + var b bytes.Buffer + cmd.Stdout = &b + cmd.Stderr = &b + if err := cmd.Start(); err != nil { + t.Fatalf("starting %s %s: %v", binary, name, err) + } + + // If the process doesn't complete within 1 minute, + // assume it is hanging and kill it to get a stack trace. + p := cmd.Process + done := make(chan bool) + go func() { + scale := 1 + // This GOARCH/GOOS test is copied from cmd/dist/test.go. + // TODO(iant): Have cmd/dist update the environment variable. + if runtime.GOARCH == "arm" || runtime.GOOS == "windows" { + scale = 2 + } + if s := os.Getenv("GO_TEST_TIMEOUT_SCALE"); s != "" { + if sc, err := strconv.Atoi(s); err == nil { + scale = sc + } + } + + select { + case <-done: + case <-time.After(time.Duration(scale) * time.Minute): + p.Signal(sigquit) + } + }() + + if err := cmd.Wait(); err != nil { + t.Logf("%s %s exit status: %v", binary, name, err) + } + close(done) + + return b.String() } func buildTestProg(t *testing.T, binary string, flags ...string) (string, error) { diff --git a/src/runtime/crash_unix_test.go b/src/runtime/crash_unix_test.go index 0a79661f1e..6e4d04bd20 100644 --- a/src/runtime/crash_unix_test.go +++ b/src/runtime/crash_unix_test.go @@ -19,6 +19,10 @@ import ( "testing" ) +// sigquit is the signal to send to kill a hanging testdata program. +// Send SIGQUIT to get a stack trace. +var sigquit = syscall.SIGQUIT + func TestCrashDumpsAllThreads(t *testing.T) { switch runtime.GOOS { case "darwin", "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris": |