diff options
author | Keith Randall <khr@golang.org> | 2014-10-18 21:02:49 -0700 |
---|---|---|
committer | Keith Randall <khr@golang.org> | 2014-10-18 21:02:49 -0700 |
commit | ad36605b757c53ef1573fea79ffd033aec48e599 (patch) | |
tree | 20406ea9697c2328aa48e31969c59d4bbb2eb801 /src/runtime/select.go | |
parent | a6baa662d04a1cebf2507dea9d030836da673c84 (diff) | |
download | go-ad36605b757c53ef1573fea79ffd033aec48e599.tar.gz |
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://codereview.appspot.com/159040043
Diffstat (limited to 'src/runtime/select.go')
-rw-r--r-- | src/runtime/select.go | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/src/runtime/select.go b/src/runtime/select.go index 9de057b87..efe68c1f5 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 |