runtime: disallow closing bubbled chans from outside bubble

A chan created within a synctest bubble may not be
operated on from outside the bubble.
We panicked on send and receive, but not close.
Panic on close as well.

For #67434

Change-Id: I98d39e0cf7baa1a679aca1fb325453d69c535308
Reviewed-on: https://go-review.googlesource.com/c/go/+/671960
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Auto-Submit: Damien Neil <dneil@google.com>
This commit is contained in:
Damien Neil 2025-05-09 16:18:49 -07:00 committed by Gopher Robot
parent b7382cc1f0
commit d596bc0e81
2 changed files with 43 additions and 0 deletions

View file

@ -263,6 +263,46 @@ func TestChannelFromOutsideBubble(t *testing.T) {
}
}
func TestChannelMovedOutOfBubble(t *testing.T) {
for _, test := range []struct {
desc string
f func(chan struct{})
wantPanic string
}{{
desc: "receive",
f: func(ch chan struct{}) {
<-ch
},
wantPanic: "receive on synctest channel from outside bubble",
}, {
desc: "send",
f: func(ch chan struct{}) {
ch <- struct{}{}
},
wantPanic: "send on synctest channel from outside bubble",
}, {
desc: "close",
f: func(ch chan struct{}) {
close(ch)
},
wantPanic: "close of synctest channel from outside bubble",
}} {
t.Run(test.desc, func(t *testing.T) {
donec := make(chan struct{})
ch := make(chan chan struct{})
go func() {
defer close(donec)
defer wantPanic(t, test.wantPanic)
test.f(<-ch)
}()
synctest.Run(func() {
ch <- make(chan struct{})
})
<-donec
})
}
}
func TestTimerFromInsideBubble(t *testing.T) {
for _, test := range []struct {
desc string

View file

@ -415,6 +415,9 @@ func closechan(c *hchan) {
if c == nil {
panic(plainError("close of nil channel"))
}
if c.synctest && getg().bubble == nil {
panic(plainError("close of synctest channel from outside bubble"))
}
lock(&c.lock)
if c.closed != 0 {