diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-05-02 14:43:35 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-05-02 14:43:35 +0000 |
commit | 34efdaf078b01a7387007c4e6bde6db86384c4b7 (patch) | |
tree | d503eaf41d085669d1481bb46ec038bc866fece6 /libgo/go/runtime/crash_unix_test.go | |
parent | f733cf303bcdc952c92b81dd62199a40a1f555ec (diff) | |
download | gcc-tarball-master.tar.gz |
gcc-7.1.0gcc-7.1.0
Diffstat (limited to 'libgo/go/runtime/crash_unix_test.go')
-rw-r--r-- | libgo/go/runtime/crash_unix_test.go | 85 |
1 files changed, 80 insertions, 5 deletions
diff --git a/libgo/go/runtime/crash_unix_test.go b/libgo/go/runtime/crash_unix_test.go index 771b303f6e..182c84b639 100644 --- a/libgo/go/runtime/crash_unix_test.go +++ b/libgo/go/runtime/crash_unix_test.go @@ -9,6 +9,7 @@ package runtime_test import ( "bytes" "internal/testenv" + "io" "io/ioutil" "os" "os/exec" @@ -19,6 +20,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": @@ -33,6 +38,8 @@ func TestCrashDumpsAllThreads(t *testing.T) { checkStaleRuntime(t) + t.Parallel() + dir, err := ioutil.TempDir("", "go-build") if err != nil { t.Fatalf("failed to create temp directory: %v", err) @@ -43,7 +50,7 @@ func TestCrashDumpsAllThreads(t *testing.T) { t.Fatalf("failed to create Go file: %v", err) } - cmd := exec.Command("go", "build", "-o", "a.exe") + cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", "a.exe") cmd.Dir = dir out, err := testEnv(cmd).CombinedOutput() if err != nil { @@ -147,12 +154,80 @@ func loop(i int, c chan bool) { } ` +func TestPanicSystemstack(t *testing.T) { + // Test that GOTRACEBACK=crash prints both the system and user + // stack of other threads. + + // The GOTRACEBACK=crash handler takes 0.1 seconds even if + // it's not writing a core file and potentially much longer if + // it is. Skip in short mode. + if testing.Short() { + t.Skip("Skipping in short mode (GOTRACEBACK=crash is slow)") + } + + t.Parallel() + cmd := exec.Command(os.Args[0], "testPanicSystemstackInternal") + cmd = testEnv(cmd) + cmd.Env = append(cmd.Env, "GOTRACEBACK=crash") + pr, pw, err := os.Pipe() + if err != nil { + t.Fatal("creating pipe: ", err) + } + cmd.Stderr = pw + if err := cmd.Start(); err != nil { + t.Fatal("starting command: ", err) + } + defer cmd.Process.Wait() + defer cmd.Process.Kill() + if err := pw.Close(); err != nil { + t.Log("closing write pipe: ", err) + } + defer pr.Close() + + // Wait for "x\nx\n" to indicate readiness. + buf := make([]byte, 4) + _, err = io.ReadFull(pr, buf) + if err != nil || string(buf) != "x\nx\n" { + t.Fatal("subprocess failed; output:\n", string(buf)) + } + + // Send SIGQUIT. + if err := cmd.Process.Signal(syscall.SIGQUIT); err != nil { + t.Fatal("signaling subprocess: ", err) + } + + // Get traceback. + tb, err := ioutil.ReadAll(pr) + if err != nil { + t.Fatal("reading traceback from pipe: ", err) + } + + // Traceback should have two testPanicSystemstackInternal's + // and two blockOnSystemStackInternal's. + if bytes.Count(tb, []byte("testPanicSystemstackInternal")) != 2 { + t.Fatal("traceback missing user stack:\n", string(tb)) + } else if bytes.Count(tb, []byte("blockOnSystemStackInternal")) != 2 { + t.Fatal("traceback missing system stack:\n", string(tb)) + } +} + +func init() { + if len(os.Args) >= 2 && os.Args[1] == "testPanicSystemstackInternal" { + // Get two threads running on the system stack with + // something recognizable in the stack trace. + runtime.GOMAXPROCS(2) + go testPanicSystemstackInternal() + testPanicSystemstackInternal() + } +} + +func testPanicSystemstackInternal() { + runtime.BlockOnSystemStack() + os.Exit(1) // Should be unreachable. +} + func TestSignalExitStatus(t *testing.T) { testenv.MustHaveGoBuild(t) - switch runtime.GOOS { - case "netbsd", "solaris": - t.Skipf("skipping on %s; see https://golang.org/issue/14063", runtime.GOOS) - } exe, err := buildTestProg(t, "testprog") if err != nil { t.Fatal(err) |