// Exit causes the current program to exit with the given status code.
// Conventionally, code zero indicates success, non-zero an error.
-// The program terminates immediately; deferred functions are
-// not run.
-func Exit(code int) { syscall.Exit(code) }
+// The program terminates immediately; deferred functions are not run.
+func Exit(code int) {
+ 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
t.Fatalf("failed to create temp directory: %v", err)
}
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)
if err != nil {
t.Fatalf("failed to create file: %v", err)
t.Fatalf("failed to close file: %v", err)
}
// 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.
for _, env := range os.Environ() {
if strings.HasPrefix(env, "GODEBUG=") ||
var tests = []struct {
name string
+ run string
gorace string
source string
re string
}{
- {"simple", "atexit_sleep_ms=0", `
+ {"simple", "run", "atexit_sleep_ms=0", `
package main
import "time"
func main() {
exit status 66
`},
- {"exitcode", "atexit_sleep_ms=0 exitcode=13", `
+ {"exitcode", "run", "atexit_sleep_ms=0 exitcode=13", `
package main
func main() {
done := make(chan bool)
}
`, `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
func main() {
done := make(chan bool)
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
func main() {
done := make(chan bool)
==================
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`},
}