aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHector Chu <hectorchu@gmail.com>2011-07-18 16:15:01 -0400
committerRuss Cox <rsc@golang.org>2011-07-18 16:15:01 -0400
commit47e6042f73b07c5eaf28b978711605025c3d0df6 (patch)
tree9c9bba2d4f64d1a2bc2925a05e408cca742e707b
parentbd77619142f6eb9212fb99ca17aade47afc001e5 (diff)
downloadgo-47e6042f73b07c5eaf28b978711605025c3d0df6.tar.gz
go-47e6042f73b07c5eaf28b978711605025c3d0df6.zip
runtime: fix select pass 3
Fixes #2075 R=rsc, ken, r CC=golang-dev https://golang.org/cl/4748045
-rw-r--r--src/pkg/runtime/chan.c9
-rw-r--r--test/chan/select6.go34
2 files changed, 40 insertions, 3 deletions
diff --git a/src/pkg/runtime/chan.c b/src/pkg/runtime/chan.c
index efaceebf5a..bbe05e041c 100644
--- a/src/pkg/runtime/chan.c
+++ b/src/pkg/runtime/chan.c
@@ -1167,12 +1167,15 @@ loop:
static void
dequeueg(WaitQ *q, Hchan *c)
{
- SudoG **l, *sgp;
-
- for(l=&q->first; (sgp=*l) != nil; l=&sgp->link) {
+ SudoG **l, *sgp, *prevsgp;
+
+ prevsgp = nil;
+ for(l=&q->first; (sgp=*l) != nil; l=&sgp->link, prevsgp=sgp) {
if(sgp->g == g) {
*l = sgp->link;
freesg(c, sgp);
+ if(q->last == sgp)
+ q->last = prevsgp;
break;
}
}
diff --git a/test/chan/select6.go b/test/chan/select6.go
new file mode 100644
index 0000000000..2ba6810ac3
--- /dev/null
+++ b/test/chan/select6.go
@@ -0,0 +1,34 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2011 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.
+
+// Issue 2075
+// A bug in select corrupts channel queues of failed cases
+// if there are multiple waiters on those channels and the
+// select is the last in the queue. If further waits are made
+// on the channel without draining it first then those waiters
+// will never wake up. In the code below c1 is such a channel.
+
+package main
+
+func main() {
+ c1 := make(chan bool)
+ c2 := make(chan bool)
+ c3 := make(chan bool)
+ go func() { <-c1 }()
+ go func() {
+ select {
+ case <-c1:
+ panic("dummy")
+ case <-c2:
+ c3 <- true
+ }
+ <-c1
+ }()
+ go func() { c2 <- true }()
+ <-c3
+ c1 <- true
+ c1 <- true
+}