From 4f86f2267167a63b673c4a2a2994e008b32c90ea Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Thu, 5 Jun 2025 13:47:06 -0700 Subject: 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 Auto-Submit: Damien Neil LUCI-TryBot-Result: Go LUCI --- src/sync/waitgroup.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src/sync') diff --git a/src/sync/waitgroup.go b/src/sync/waitgroup.go index efc63be099..0bd618a241 100644 --- a/src/sync/waitgroup.go +++ b/src/sync/waitgroup.go @@ -83,13 +83,17 @@ func (wg *WaitGroup) Add(delta int) { race.Disable() defer race.Enable() } + bubbled := false if synctest.IsInBubble() { // If Add is called from within a bubble, then all Add calls must be made // from the same bubble. - if !synctest.Associate(wg) { + switch synctest.Associate(wg) { + case synctest.Unbubbled: + case synctest.OtherBubble: // wg is already associated with a different bubble. fatal("sync: WaitGroup.Add called from multiple synctest bubbles") - } else { + case synctest.CurrentBubble: + bubbled = true state := wg.state.Or(waitGroupBubbleFlag) if state != 0 && state&waitGroupBubbleFlag == 0 { // Add has been called from outside this bubble. @@ -98,7 +102,7 @@ func (wg *WaitGroup) Add(delta int) { } } state := wg.state.Add(uint64(delta) << 32) - if state&waitGroupBubbleFlag != 0 && !synctest.IsInBubble() { + if state&waitGroupBubbleFlag != 0 && !bubbled { // Add has been called from within a synctest bubble (and we aren't in one). fatal("sync: WaitGroup.Add called from inside and outside synctest bubble") } @@ -116,7 +120,7 @@ func (wg *WaitGroup) Add(delta int) { if w != 0 && delta > 0 && v == int32(delta) { panic("sync: WaitGroup misuse: Add called concurrently with Wait") } - if v == 0 && state&waitGroupBubbleFlag != 0 { + if v == 0 && bubbled { // Disassociate the WaitGroup from its bubble. synctest.Disassociate(wg) if w == 0 { -- cgit v1.3