mirror of
https://github.com/golang/go
synced 2024-11-23 06:30:06 -07:00
os: give race detector chance to override Exit(0)
Racy tests do not fail currently, they do os.Exit(0). So if you run go test without -v, you won't even notice. This was probably introduced with testing.TestMain. Racy programs do not have the right to finish successfully. Change-Id: Id133d7424f03d90d438bc3478528683dd02b8846 Reviewed-on: https://go-review.googlesource.com/4371 Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
7b2b45e544
commit
c61d86af72
@ -44,6 +44,14 @@ func Getgroups() ([]int, error) {
|
|||||||
|
|
||||||
// Exit causes the current program to exit with the given status code.
|
// Exit causes the current program to exit with the given status code.
|
||||||
// Conventionally, code zero indicates success, non-zero an error.
|
// Conventionally, code zero indicates success, non-zero an error.
|
||||||
// The program terminates immediately; deferred functions are
|
// The program terminates immediately; deferred functions are not run.
|
||||||
// not run.
|
func Exit(code int) {
|
||||||
func Exit(code int) { syscall.Exit(code) }
|
if code == 0 {
|
||||||
|
// Give race detector a chance to fail the program.
|
||||||
|
// Racy programs do not have the right to finish successfully.
|
||||||
|
runtime_beforeExit()
|
||||||
|
}
|
||||||
|
syscall.Exit(code)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runtime_beforeExit() // implemented in runtime
|
||||||
|
@ -105,6 +105,14 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// os_beforeExit is called from os.Exit(0).
|
||||||
|
//go:linkname os_beforeExit os.runtime_beforeExit
|
||||||
|
func os_beforeExit() {
|
||||||
|
if raceenabled {
|
||||||
|
racefini()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// start forcegc helper goroutine
|
// start forcegc helper goroutine
|
||||||
func init() {
|
func init() {
|
||||||
go forcegchelper()
|
go forcegchelper()
|
||||||
|
@ -23,7 +23,11 @@ func TestOutput(t *testing.T) {
|
|||||||
t.Fatalf("failed to create temp directory: %v", err)
|
t.Fatalf("failed to create temp directory: %v", err)
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(dir)
|
defer os.RemoveAll(dir)
|
||||||
src := filepath.Join(dir, "main.go")
|
source := "main.go"
|
||||||
|
if test.run == "test" {
|
||||||
|
source = "main_test.go"
|
||||||
|
}
|
||||||
|
src := filepath.Join(dir, source)
|
||||||
f, err := os.Create(src)
|
f, err := os.Create(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create file: %v", err)
|
t.Fatalf("failed to create file: %v", err)
|
||||||
@ -37,7 +41,7 @@ func TestOutput(t *testing.T) {
|
|||||||
t.Fatalf("failed to close file: %v", err)
|
t.Fatalf("failed to close file: %v", err)
|
||||||
}
|
}
|
||||||
// Pass -l to the compiler to test stack traces.
|
// Pass -l to the compiler to test stack traces.
|
||||||
cmd := exec.Command("go", "run", "-race", "-gcflags=-l", src)
|
cmd := exec.Command("go", test.run, "-race", "-gcflags=-l", src)
|
||||||
// GODEBUG spoils program output, GOMAXPROCS makes it flaky.
|
// GODEBUG spoils program output, GOMAXPROCS makes it flaky.
|
||||||
for _, env := range os.Environ() {
|
for _, env := range os.Environ() {
|
||||||
if strings.HasPrefix(env, "GODEBUG=") ||
|
if strings.HasPrefix(env, "GODEBUG=") ||
|
||||||
@ -58,11 +62,12 @@ func TestOutput(t *testing.T) {
|
|||||||
|
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
name string
|
name string
|
||||||
|
run string
|
||||||
gorace string
|
gorace string
|
||||||
source string
|
source string
|
||||||
re string
|
re string
|
||||||
}{
|
}{
|
||||||
{"simple", "atexit_sleep_ms=0", `
|
{"simple", "run", "atexit_sleep_ms=0", `
|
||||||
package main
|
package main
|
||||||
import "time"
|
import "time"
|
||||||
func main() {
|
func main() {
|
||||||
@ -107,7 +112,7 @@ Found 1 data race\(s\)
|
|||||||
exit status 66
|
exit status 66
|
||||||
`},
|
`},
|
||||||
|
|
||||||
{"exitcode", "atexit_sleep_ms=0 exitcode=13", `
|
{"exitcode", "run", "atexit_sleep_ms=0 exitcode=13", `
|
||||||
package main
|
package main
|
||||||
func main() {
|
func main() {
|
||||||
done := make(chan bool)
|
done := make(chan bool)
|
||||||
@ -121,7 +126,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
`, `exit status 13`},
|
`, `exit status 13`},
|
||||||
|
|
||||||
{"strip_path_prefix", "atexit_sleep_ms=0 strip_path_prefix=/main.", `
|
{"strip_path_prefix", "run", "atexit_sleep_ms=0 strip_path_prefix=/main.", `
|
||||||
package main
|
package main
|
||||||
func main() {
|
func main() {
|
||||||
done := make(chan bool)
|
done := make(chan bool)
|
||||||
@ -137,7 +142,7 @@ func main() {
|
|||||||
go:7 \+0x[0-9,a-f]+
|
go:7 \+0x[0-9,a-f]+
|
||||||
`},
|
`},
|
||||||
|
|
||||||
{"halt_on_error", "atexit_sleep_ms=0 halt_on_error=1", `
|
{"halt_on_error", "run", "atexit_sleep_ms=0 halt_on_error=1", `
|
||||||
package main
|
package main
|
||||||
func main() {
|
func main() {
|
||||||
done := make(chan bool)
|
done := make(chan bool)
|
||||||
@ -153,4 +158,23 @@ func main() {
|
|||||||
==================
|
==================
|
||||||
exit status 66
|
exit status 66
|
||||||
`},
|
`},
|
||||||
|
|
||||||
|
{"test_fails_on_race", "test", "atexit_sleep_ms=0", `
|
||||||
|
package main_test
|
||||||
|
import "testing"
|
||||||
|
func TestFail(t *testing.T) {
|
||||||
|
done := make(chan bool)
|
||||||
|
x := 0
|
||||||
|
go func() {
|
||||||
|
x = 42
|
||||||
|
done <- true
|
||||||
|
}()
|
||||||
|
x = 43
|
||||||
|
<-done
|
||||||
|
}
|
||||||
|
`, `
|
||||||
|
==================
|
||||||
|
PASS
|
||||||
|
Found 1 data race\(s\)
|
||||||
|
FAIL`},
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user