aboutsummaryrefslogtreecommitdiff
path: root/src/internal
diff options
context:
space:
mode:
authorDamien Neil <dneil@google.com>2025-06-05 13:47:06 -0700
committerGopher Robot <gobot@golang.org>2025-06-10 15:02:26 -0700
commit4f86f2267167a63b673c4a2a2994e008b32c90ea (patch)
tree24dd8afd3e0e54897f199a95a151ccd5be83fab7 /src/internal
parent773701a853a3105696c59c2b92b2eff35e0e055b (diff)
downloadgo-4f86f2267167a63b673c4a2a2994e008b32c90ea.tar.xz
testing/synctest, runtime: avoid panic when using linker-alloc WG from bubble
We associate WaitGroups with synctest bubbles by attaching a special to the WaitGroup. It is not possible to attach a special to a linker-allocated value, such as: var wg sync.WaitGroup Avoid panicking when accessing a linker-allocated WaitGroup from a bubble. We have no way to associate these WaitGroups with a bubble, so just treat them as always unbubbled. This is probably fine, since the WaitGroup was always created outside the bubble in this case. Fixes #74005 Change-Id: Ic71514b0b8d0cecd62e45cc929ffcbeb16f54a55 Reviewed-on: https://go-review.googlesource.com/c/go/+/679695 Reviewed-by: Michael Knyszek <mknyszek@google.com> Auto-Submit: Damien Neil <dneil@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Diffstat (limited to 'src/internal')
-rw-r--r--src/internal/synctest/synctest.go22
-rw-r--r--src/internal/synctest/synctest_test.go28
2 files changed, 45 insertions, 5 deletions
diff --git a/src/internal/synctest/synctest.go b/src/internal/synctest/synctest.go
index 4d7fa3730c..cb3333a627 100644
--- a/src/internal/synctest/synctest.go
+++ b/src/internal/synctest/synctest.go
@@ -8,6 +8,7 @@
package synctest
import (
+ "internal/abi"
"unsafe"
)
@@ -22,14 +23,25 @@ func Wait()
//go:linkname IsInBubble
func IsInBubble() bool
-// Associate associates p with the current bubble.
-// It returns false if p has an existing association with a different bubble.
-func Associate[T any](p *T) (ok bool) {
- return associate(unsafe.Pointer(p))
+// Association is the state of a pointer's bubble association.
+type Association int
+
+const (
+ Unbubbled = Association(iota) // not associated with any bubble
+ CurrentBubble // associated with the current bubble
+ OtherBubble // associated with a different bubble
+)
+
+// Associate attempts to associate p with the current bubble.
+// It returns the new association status of p.
+func Associate[T any](p *T) Association {
+ // Ensure p escapes to permit us to attach a special to it.
+ escapedP := abi.Escape(p)
+ return Association(associate(unsafe.Pointer(escapedP)))
}
//go:linkname associate
-func associate(p unsafe.Pointer) bool
+func associate(p unsafe.Pointer) int
// Disassociate disassociates p from any bubble.
func Disassociate[T any](p *T) {
diff --git a/src/internal/synctest/synctest_test.go b/src/internal/synctest/synctest_test.go
index fe6eb63702..222cae2597 100644
--- a/src/internal/synctest/synctest_test.go
+++ b/src/internal/synctest/synctest_test.go
@@ -731,6 +731,34 @@ func TestWaitGroupMovedBetweenBubblesAfterWait(t *testing.T) {
})
}
+var testWaitGroupLinkerAllocatedWG sync.WaitGroup
+
+func TestWaitGroupLinkerAllocated(t *testing.T) {
+ synctest.Run(func() {
+ // This WaitGroup is probably linker-allocated and has no span,
+ // so we won't be able to add a special to it associating it with
+ // this bubble.
+ //
+ // Operations on it may not be durably blocking,
+ // but they shouldn't fail.
+ testWaitGroupLinkerAllocatedWG.Go(func() {})
+ testWaitGroupLinkerAllocatedWG.Wait()
+ })
+}
+
+var testWaitGroupHeapAllocatedWG = new(sync.WaitGroup)
+
+func TestWaitGroupHeapAllocated(t *testing.T) {
+ synctest.Run(func() {
+ // This package-scoped WaitGroup var should have been heap-allocated,
+ // so we can associate it with a bubble.
+ testWaitGroupHeapAllocatedWG.Add(1)
+ go testWaitGroupHeapAllocatedWG.Wait()
+ synctest.Wait()
+ testWaitGroupHeapAllocatedWG.Done()
+ })
+}
+
func TestHappensBefore(t *testing.T) {
// Use two parallel goroutines accessing different vars to ensure that
// we correctly account for multiple goroutines in the bubble.