]> Cypherpunks repositories - gostls13.git/commitdiff
sync: deflake TestWaitGroupMisuse2
authorMichael Munday <mike.munday@ibm.com>
Sun, 13 May 2018 07:13:56 +0000 (08:13 +0100)
committerBrad Fitzpatrick <bradfitz@golang.org>
Mon, 14 May 2018 04:42:45 +0000 (04:42 +0000)
We need to yield to the runtime every now and again to avoid
deadlock. This doesn't show up on most machines because the test
only runs when you have 5 or more CPUs.

Fixes #20072.

Change-Id: Ibf5ed370e919943395f3418487188df0b2be160b
Reviewed-on: https://go-review.googlesource.com/112978
Run-TryBot: Michael Munday <mike.munday@ibm.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/sync/waitgroup_test.go

index e3e30966457bf7f1f09e9c772d538821c633ed9d..4ab438cbab1c1e19504448b39ca0f9928c47f13a 100644 (file)
@@ -68,6 +68,21 @@ func TestWaitGroupMisuse(t *testing.T) {
        t.Fatal("Should panic")
 }
 
+// pollUntilEqual blocks until v, loaded atomically, is
+// equal to the target.
+func pollUntilEqual(v *uint32, target uint32) {
+       for {
+               for i := 0; i < 1e3; i++ {
+                       if atomic.LoadUint32(v) == target {
+                               return
+                       }
+               }
+               // yield to avoid deadlock with the garbage collector
+               // see issue #20072
+               runtime.Gosched()
+       }
+}
+
 func TestWaitGroupMisuse2(t *testing.T) {
        knownRacy(t)
        if runtime.NumCPU() <= 4 {
@@ -94,9 +109,7 @@ func TestWaitGroupMisuse2(t *testing.T) {
                                done <- recover()
                        }()
                        atomic.AddUint32(&here, 1)
-                       for atomic.LoadUint32(&here) != 3 {
-                               // spin
-                       }
+                       pollUntilEqual(&here, 3)
                        wg.Wait()
                }()
                go func() {
@@ -104,16 +117,12 @@ func TestWaitGroupMisuse2(t *testing.T) {
                                done <- recover()
                        }()
                        atomic.AddUint32(&here, 1)
-                       for atomic.LoadUint32(&here) != 3 {
-                               // spin
-                       }
+                       pollUntilEqual(&here, 3)
                        wg.Add(1) // This is the bad guy.
                        wg.Done()
                }()
                atomic.AddUint32(&here, 1)
-               for atomic.LoadUint32(&here) != 3 {
-                       // spin
-               }
+               pollUntilEqual(&here, 3)
                wg.Done()
                for j := 0; j < 2; j++ {
                        if err := <-done; err != nil {