Commit 37b7880d authored by Austin Clements's avatar Austin Clements

runtime: use SIGKILL if SIGQUIT is blocked; skip tests that need SIGQUIT

The runtime tests may be invoked from a parent that has SIGQUIT
blocked. For example, Java invokes subprocesses this way. In this
situation, TestCrashDumpsAllThreads and TestPanicSystemstack will fail
because they depend on SIGQUIT to get tracebacks, and any subprocess
test that times out will fail to kill the subprocess.

Fix this by detecting if SIGQUIT is blocked and, if so, skipping tests
that depend on it and using SIGKILL to kill timed-out subprocesses.

Based on a fix by Carl Henrik Lunde in
https://golang.org/issue/19196#issuecomment-316145733

Fixes #19196.

Change-Id: Ia20bf15b96086487d0ef6b75239dcc260c21714c
Reviewed-on: https://go-review.googlesource.com/50330
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 28f650a2
......@@ -24,6 +24,15 @@ import (
// Send SIGQUIT to get a stack trace.
var sigquit = syscall.SIGQUIT
func init() {
if runtime.Sigisblocked(int(syscall.SIGQUIT)) {
// We can't use SIGQUIT to kill subprocesses because
// it's blocked. Use SIGKILL instead. See issue
// #19196 for an example of when this happens.
sigquit = syscall.SIGKILL
}
}
func TestCrashDumpsAllThreads(t *testing.T) {
switch runtime.GOOS {
case "darwin", "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
......@@ -31,6 +40,10 @@ func TestCrashDumpsAllThreads(t *testing.T) {
t.Skipf("skipping; not supported on %v", runtime.GOOS)
}
if runtime.Sigisblocked(int(syscall.SIGQUIT)) {
t.Skip("skipping; SIGQUIT is blocked, see golang.org/issue/19196")
}
// We don't use executeTest because we need to kill the
// program while it is running.
......@@ -165,6 +178,10 @@ func TestPanicSystemstack(t *testing.T) {
t.Skip("Skipping in short mode (GOTRACEBACK=crash is slow)")
}
if runtime.Sigisblocked(int(syscall.SIGQUIT)) {
t.Skip("skipping; SIGQUIT is blocked, see golang.org/issue/19196")
}
t.Parallel()
cmd := exec.Command(os.Args[0], "testPanicSystemstackInternal")
cmd = testEnv(cmd)
......
// Copyright 2017 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 darwin dragonfly freebsd linux netbsd openbsd solaris
package runtime
func sigismember(mask *sigset, i int) bool {
clear := *mask
sigdelset(&clear, i)
return clear != *mask
}
func Sigisblocked(i int) bool {
var sigmask sigset
sigprocmask(_SIG_SETMASK, nil, &sigmask)
return sigismember(&sigmask, i)
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment