1
0
mirror of https://github.com/golang/go synced 2024-11-23 05:00:07 -07:00

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>
This commit is contained in:
Ian Lance Taylor 2016-06-14 14:38:22 -07:00
parent 48cc3c4b58
commit 26d6dc6bf8
3 changed files with 59 additions and 2 deletions

View File

@ -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

View File

@ -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) {

View File

@ -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":