diff options
author | Russ Cox <rsc@golang.org> | 2011-01-21 15:06:44 -0500 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2011-01-21 15:06:44 -0500 |
commit | 0a5fc261b65aff5c66033eb22edd6f7acd4f6bbd (patch) | |
tree | eafe50b9149c29a16995808c52aea0df200844fa /test/chan | |
parent | 5b5a674b4665f0ca140dd210b319356de21d9184 (diff) | |
download | go-0a5fc261b65aff5c66033eb22edd6f7acd4f6bbd.tar.gz go-0a5fc261b65aff5c66033eb22edd6f7acd4f6bbd.zip |
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
https://golang.org/cl/4008046
Diffstat (limited to 'test/chan')
-rw-r--r-- | test/chan/doubleselect.go | 36 |
1 files changed, 19 insertions, 17 deletions
diff --git a/test/chan/doubleselect.go b/test/chan/doubleselect.go index 592d2f54a4..3c7412ed6a 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") } |