// Copyright 2018 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. // Stress the interaction between the race detector and cgo in an // attempt to reproduce the memory corruption described in #27660. // The bug was very timing sensitive; at the time of writing this // test would only trigger the bug about once out of every five runs. package cgotest // #include <unistd.h> import "C" import ( "context" "math/rand" "runtime" "sync" "testing" "time" ) func test27660(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() ints := make([]int, 100) locks := make([]sync.Mutex, 100) // Slowly create threads so that ThreadSanitizer is forced to // frequently resize its SyncClocks. for i := 0; i < 100; i++ { go func() { for ctx.Err() == nil { // Sleep in C for long enough that it is likely that the runtime // will retake this goroutine's currently wired P. C.usleep(1000 /* 1ms */) runtime.Gosched() // avoid starvation (see #28701) } }() go func() { // Trigger lots of synchronization and memory reads/writes to // increase the likelihood that the race described in #27660 // results in corruption of ThreadSanitizer's internal state // and thus an assertion failure or segfault. for ctx.Err() == nil { j := rand.Intn(100) locks[j].Lock() ints[j]++ locks[j].Unlock() } }() time.Sleep(time.Millisecond) } }