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 {
// 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")
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")
}