Commit 0a5fc261 authored by Russ Cox's avatar Russ Cox

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
parent 5b5a674b
...@@ -21,6 +21,8 @@ var iterations *int = flag.Int("n", 100000, "number of iterations") ...@@ -21,6 +21,8 @@ var iterations *int = flag.Int("n", 100000, "number of iterations")
func sender(n int, c1, c2, c3, c4 chan<- int) { func sender(n int, c1, c2, c3, c4 chan<- int) {
defer close(c1) defer close(c1)
defer close(c2) defer close(c2)
defer close(c3)
defer close(c4)
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
select { select {
...@@ -35,26 +37,18 @@ func sender(n int, c1, c2, c3, c4 chan<- int) { ...@@ -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. // 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 // It would be simplier to just have sender's four cases all be the same
// channel, but this doesn't actually trigger the bug. // channel, but this doesn't actually trigger the bug.
func mux(out chan<- int, in <-chan int) { func mux(out chan<- int, in <-chan int, done chan<- bool) {
for { for v := range in {
v := <-in
if closed(in) {
close(out)
break
}
out <- v out <- v
} }
done <- true
} }
// recver gets a steam of values from the four mux's and checks for duplicates. // recver gets a steam of values from the four mux's and checks for duplicates.
func recver(in <-chan int) { func recver(in <-chan int) {
seen := make(map[int]bool) seen := make(map[int]bool)
for { for v := range in {
v := <-in
if closed(in) {
break
}
if _, ok := seen[v]; ok { if _, ok := seen[v]; ok {
println("got duplicate value: ", v) println("got duplicate value: ", v)
panic("fail") panic("fail")
...@@ -70,15 +64,23 @@ func main() { ...@@ -70,15 +64,23 @@ func main() {
c2 := make(chan int) c2 := make(chan int)
c3 := make(chan int) c3 := make(chan int)
c4 := make(chan int) c4 := make(chan int)
done := make(chan bool)
cmux := make(chan int) cmux := make(chan int)
go sender(*iterations, c1, c2, c3, c4) go sender(*iterations, c1, c2, c3, c4)
go mux(cmux, c1) go mux(cmux, c1, done)
go mux(cmux, c2) go mux(cmux, c2, done)
go mux(cmux, c3) go mux(cmux, c3, done)
go mux(cmux, c4) 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. // 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 // 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) recver(cmux)
print("PASS\n") print("PASS\n")
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment