]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: establish happens-before between goroutine and bubble exit
authorDamien Neil <dneil@google.com>
Fri, 7 Feb 2025 17:55:15 +0000 (09:55 -0800)
committerGopher Robot <gobot@golang.org>
Mon, 10 Feb 2025 18:48:27 +0000 (10:48 -0800)
synctest.Run waits for all bubbled goroutines to exit before returning.
Establish a happens-before relationship between the bubbled goroutines
exiting and Run returning.

For #67434

Change-Id: Ibda7ec2075ae50838c0851e60dc5b3c6f3ca70fb
Reviewed-on: https://go-review.googlesource.com/c/go/+/647755
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Damien Neil <dneil@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
src/internal/synctest/synctest_test.go
src/runtime/synctest.go

index 7d1e04e2ba34e21d23a45a0ad5866ec62e67de30..450d5f54166943ec2be181ce05cbfda07ba52364 100644 (file)
@@ -433,6 +433,32 @@ func TestWaitGroup(t *testing.T) {
        })
 }
 
+func TestHappensBefore(t *testing.T) {
+       var v int
+       synctest.Run(func() {
+               go func() {
+                       v++ // 1
+               }()
+               // Wait creates a happens-before relationship on the above goroutine exiting.
+               synctest.Wait()
+               go func() {
+                       v++ // 2
+               }()
+       })
+       // Run exiting creates a happens-before relationship on goroutines started in the bubble.
+       synctest.Run(func() {
+               v++ // 3
+               // There is a happens-before relationship between the time.AfterFunc call,
+               // and the func running.
+               time.AfterFunc(0, func() {
+                       v++ // 4
+               })
+       })
+       if got, want := v, 4; got != want {
+               t.Errorf("v = %v, want %v", got, want)
+       }
+}
+
 func wantPanic(t *testing.T, want string) {
        if e := recover(); e != nil {
                if got := fmt.Sprint(e); got != want {
index 498c3b92dd07966c178a4afa1347e2f4697f7a75..65bb15dfbb04554e5393b93b9d1051a2bb34508d 100644 (file)
@@ -182,6 +182,8 @@ func synctestRun(f func()) {
        sg.active++
        for {
                if raceenabled {
+                       // Establish a happens-before relationship between a timer being created,
+                       // and the timer running.
                        raceacquireg(gp, gp.syncGroup.raceaddr())
                }
                unlock(&sg.mu)
@@ -205,6 +207,11 @@ func synctestRun(f func()) {
 
        total := sg.total
        unlock(&sg.mu)
+       if raceenabled {
+               // Establish a happens-before relationship between bubbled goroutines exiting
+               // and Run returning.
+               raceacquireg(gp, gp.syncGroup.raceaddr())
+       }
        if total != 1 {
                panic("deadlock: all goroutines in bubble are blocked")
        }