runtime: print fatal messages without interleaving

Grab the print lock around the set of prints we use to report
fatal errors. This ensures that each fatal error gets reported
atomically instead of interleaved with other fatal errors.

Fixes #69447

Change-Id: Ib3569f0c8210fd7e19a7d8ef4bc114f07469f317
Reviewed-on: https://go-review.googlesource.com/c/go/+/615655
Auto-Submit: Keith Randall <khr@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Keith Randall 2024-09-24 15:11:54 -07:00 committed by Gopher Robot
parent b17a55d095
commit 6cb107452a
2 changed files with 29 additions and 3 deletions

View file

@ -621,7 +621,7 @@ func TestConcurrentMapWrites(t *testing.T) {
}
testenv.MustHaveGoRun(t)
output := runTestProg(t, "testprog", "concurrentMapWrites")
want := "fatal error: concurrent map writes"
want := "fatal error: concurrent map writes\n"
if !strings.HasPrefix(output, want) {
t.Fatalf("output does not start with %q:\n%s", want, output)
}
@ -632,7 +632,7 @@ func TestConcurrentMapReadWrite(t *testing.T) {
}
testenv.MustHaveGoRun(t)
output := runTestProg(t, "testprog", "concurrentMapReadWrite")
want := "fatal error: concurrent map read and map write"
want := "fatal error: concurrent map read and map write\n"
if !strings.HasPrefix(output, want) {
t.Fatalf("output does not start with %q:\n%s", want, output)
}
@ -643,12 +643,36 @@ func TestConcurrentMapIterateWrite(t *testing.T) {
}
testenv.MustHaveGoRun(t)
output := runTestProg(t, "testprog", "concurrentMapIterateWrite")
want := "fatal error: concurrent map iteration and map write"
want := "fatal error: concurrent map iteration and map write\n"
if !strings.HasPrefix(output, want) {
t.Fatalf("output does not start with %q:\n%s", want, output)
}
}
func TestConcurrentMapWritesIssue69447(t *testing.T) {
testenv.MustHaveGoRun(t)
exe, err := buildTestProg(t, "testprog")
if err != nil {
t.Fatal(err)
}
for i := 0; i < 200; i++ {
output := runBuiltTestProg(t, exe, "concurrentMapWrites")
if output == "" {
// If we didn't detect an error, that's ok.
// This case makes this test not flaky like
// the other ones above.
// (More correctly, this case makes this test flaky
// in the other direction, in that it might not
// detect a problem even if there is one.)
continue
}
want := "fatal error: concurrent map writes\n"
if !strings.HasPrefix(output, want) {
t.Fatalf("output does not start with %q:\n%s", want, output)
}
}
}
type point struct {
x, y *int
}