summaryrefslogtreecommitdiff
path: root/test/chan
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2011-01-21 15:06:44 -0500
committerRuss Cox <rsc@golang.org>2011-01-21 15:06:44 -0500
commit2f0305d44a17fd9a4cf2ec6b6708d67c44f2a82e (patch)
treefae69c67d3dc039729ec5e057621d356a6b34598 /test/chan
parenta4807496ed534a2b888a5346472f73382e43e021 (diff)
downloadgo-2f0305d44a17fd9a4cf2ec6b6708d67c44f2a82e.tar.gz
test/chan/doubleselect: fix various races
There were duplicate closes and missing closes, with the result that the program was rarely testing as much as it seemed to be. Now it finishes. R=r CC=golang-dev http://codereview.appspot.com/4008046
Diffstat (limited to 'test/chan')
-rw-r--r--test/chan/doubleselect.go36
1 files changed, 19 insertions, 17 deletions
diff --git a/test/chan/doubleselect.go b/test/chan/doubleselect.go
index 592d2f54a..3c7412ed6 100644
--- a/test/chan/doubleselect.go
+++ b/test/chan/doubleselect.go
@@ -21,6 +21,8 @@ var iterations *int = flag.Int("n", 100000, "number of iterations")
func sender(n int, c1, c2, c3, c4 chan<- int) {
defer close(c1)
defer close(c2)
+ defer close(c3)
+ defer close(c4)
for i := 0; i < n; i++ {
select {
@@ -35,26 +37,18 @@ func sender(n int, c1, c2, c3, c4 chan<- int) {
// mux receives the values from sender and forwards them onto another channel.
// It would be simplier to just have sender's four cases all be the same
// channel, but this doesn't actually trigger the bug.
-func mux(out chan<- int, in <-chan int) {
- for {
- v := <-in
- if closed(in) {
- close(out)
- break
- }
+func mux(out chan<- int, in <-chan int, done chan<- bool) {
+ for v := range in {
out <- v
}
+ done <- true
}
// recver gets a steam of values from the four mux's and checks for duplicates.
func recver(in <-chan int) {
seen := make(map[int]bool)
- for {
- v := <-in
- if closed(in) {
- break
- }
+ for v := range in {
if _, ok := seen[v]; ok {
println("got duplicate value: ", v)
panic("fail")
@@ -70,15 +64,23 @@ func main() {
c2 := make(chan int)
c3 := make(chan int)
c4 := make(chan int)
+ done := make(chan bool)
cmux := make(chan int)
go sender(*iterations, c1, c2, c3, c4)
- go mux(cmux, c1)
- go mux(cmux, c2)
- go mux(cmux, c3)
- go mux(cmux, c4)
+ go mux(cmux, c1, done)
+ go mux(cmux, c2, done)
+ go mux(cmux, c3, done)
+ go mux(cmux, c4, done)
+ go func() {
+ <-done
+ <-done
+ <-done
+ <-done
+ close(cmux)
+ }()
// We keep the recver because it might catch more bugs in the future.
// However, the result of the bug linked to at the top is that we'll
- // end up panicing with: "throw: bad g->status in ready".
+ // end up panicking with: "throw: bad g->status in ready".
recver(cmux)
print("PASS\n")
}