aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/select.go
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2014-10-18 21:02:49 -0700
committerKeith Randall <khr@golang.org>2014-10-18 21:02:49 -0700
commite330cc16f477471c11f78a88c8a71a155a9ca8ec (patch)
tree51c2cb1e68d797e654f375d49055e4bbdc381bb4 /src/runtime/select.go
parent1cd78eedd092c9ec10f1b5c626b8bcd0298e065f (diff)
downloadgo-e330cc16f477471c11f78a88c8a71a155a9ca8ec.tar.xz
runtime: dequeue the correct SudoG
select { case <- c: case <- c: } In this case, c.recvq lists two SudoGs which have the same G. So we can't use the G as the key to dequeue the correct SudoG, as that key is ambiguous. Dequeueing the wrong SudoG ends up freeing a SudoG that is still in c.recvq. The fix is to use the actual SudoG pointer as the key. LGTM=dvyukov R=rsc, bradfitz, dvyukov, khr CC=austin, golang-codereviews https://golang.org/cl/159040043
Diffstat (limited to 'src/runtime/select.go')
-rw-r--r--src/runtime/select.go8
1 files changed, 4 insertions, 4 deletions
diff --git a/src/runtime/select.go b/src/runtime/select.go
index 9de057b871..efe68c1f5c 100644
--- a/src/runtime/select.go
+++ b/src/runtime/select.go
@@ -398,9 +398,9 @@ loop:
} else {
c = k._chan
if k.kind == _CaseSend {
- c.sendq.dequeueg(gp)
+ c.sendq.dequeueSudoG(sglist)
} else {
- c.recvq.dequeueg(gp)
+ c.recvq.dequeueSudoG(sglist)
}
}
sgnext = sglist.waitlink
@@ -628,7 +628,7 @@ func reflect_rselect(cases []runtimeSelect) (chosen int, recvOK bool) {
return
}
-func (q *waitq) dequeueg(gp *g) {
+func (q *waitq) dequeueSudoG(s *sudog) {
var prevsgp *sudog
l := &q.first
for {
@@ -636,7 +636,7 @@ func (q *waitq) dequeueg(gp *g) {
if sgp == nil {
return
}
- if sgp.g == gp {
+ if sgp == s {
*l = sgp.next
if q.last == sgp {
q.last = prevsgp