/usr/share/go-1.6/test/chan/doubleselect.go is in golang-1.6-src 1.6.1-0ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | // run
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Test the situation in which two cases of a select can
// both end up running. See http://codereview.appspot.com/180068.
package main
import (
"flag"
"runtime"
)
var iterations *int = flag.Int("n", 100000, "number of iterations")
// sender sends a counter to one of four different channels. If two
// cases both end up running in the same iteration, the same value will be sent
// to two different channels.
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 {
case c1 <- i:
case c2 <- i:
case c3 <- i:
case c4 <- i:
}
}
}
// mux receives the values from sender and forwards them onto another channel.
// It would be simpler 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, 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 := range in {
if _, ok := seen[v]; ok {
println("got duplicate value: ", v)
panic("fail")
}
seen[v] = true
}
}
func main() {
runtime.GOMAXPROCS(2)
c1 := make(chan int)
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, 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 panicking with: "throw: bad g->status in ready".
recver(cmux)
}
|