diff options
author | Ian Lance Taylor <iant@golang.org> | 2016-07-07 17:43:08 -0700 |
---|---|---|
committer | Andrew Gerrand <adg@golang.org> | 2016-07-08 02:05:40 +0000 |
commit | 84bb9e62f06dbb62279241fa0bd7a6c8846271ac (patch) | |
tree | 6529e2381816c0789f1c06a0cf2899ddf37ffacd /src/runtime/chan_test.go | |
parent | e5ff529679b3adbed06d509b0fc21a76b62e89e9 (diff) | |
download | go-84bb9e62f06dbb62279241fa0bd7a6c8846271ac.tar.gz go-84bb9e62f06dbb62279241fa0bd7a6c8846271ac.zip |
runtime: handle selects with duplicate channels in shrinkstack
The shrinkstack code locks all the channels a goroutine is waiting for,
but didn't handle the case of the same channel appearing in the list
multiple times. This led to a deadlock. The channels are sorted so it's
easy to avoid locking the same channel twice.
Fixes #16286.
Change-Id: Ie514805d0532f61c942e85af5b7b8ac405e2ff65
Reviewed-on: https://go-review.googlesource.com/24815
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
Diffstat (limited to 'src/runtime/chan_test.go')
-rw-r--r-- | src/runtime/chan_test.go | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/src/runtime/chan_test.go b/src/runtime/chan_test.go index 219f2b449b..8e8c47b48d 100644 --- a/src/runtime/chan_test.go +++ b/src/runtime/chan_test.go @@ -593,8 +593,10 @@ func TestSelectStackAdjust(t *testing.T) { // pointers are adjusted correctly by stack shrinking. c := make(chan *int) d := make(chan *int) - ready := make(chan bool) - go func() { + ready1 := make(chan bool) + ready2 := make(chan bool) + + f := func(ready chan bool, dup bool) { // Temporarily grow the stack to 10K. stackGrowthRecursive((10 << 10) / (128 * 8)) @@ -604,10 +606,20 @@ func TestSelectStackAdjust(t *testing.T) { val := 42 var cx *int cx = &val + + var c2 chan *int + var d2 chan *int + if dup { + c2 = c + d2 = d + } + // Receive from d. cx won't be affected. select { case cx = <-c: + case <-c2: case <-d: + case <-d2: } // Check that pointer in cx was adjusted correctly. @@ -622,10 +634,14 @@ func TestSelectStackAdjust(t *testing.T) { } } ready <- true - }() + } + + go f(ready1, false) + go f(ready2, true) - // Let the goroutine get into the select. - <-ready + // Let the goroutines get into the select. + <-ready1 + <-ready2 time.Sleep(10 * time.Millisecond) // Force concurrent GC a few times. @@ -642,9 +658,10 @@ func TestSelectStackAdjust(t *testing.T) { done: selectSink = nil - // Wake select. - d <- nil - <-ready + // Wake selects. + close(d) + <-ready1 + <-ready2 } func BenchmarkChanNonblocking(b *testing.B) { |