aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/stack.go
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2016-07-07 17:43:08 -0700
committerAndrew Gerrand <adg@golang.org>2016-07-08 02:05:40 +0000
commit84bb9e62f06dbb62279241fa0bd7a6c8846271ac (patch)
tree6529e2381816c0789f1c06a0cf2899ddf37ffacd /src/runtime/stack.go
parente5ff529679b3adbed06d509b0fc21a76b62e89e9 (diff)
downloadgo-84bb9e62f06dbb62279241fa0bd7a6c8846271ac.tar.xz
runtime: handle selects with duplicate channels in shrinkstack
The shrinkstack code locks all the channels a goroutine is waiting for, but didn't handle the case of the same channel appearing in the list multiple times. This led to a deadlock. The channels are sorted so it's easy to avoid locking the same channel twice. Fixes #16286. Change-Id: Ie514805d0532f61c942e85af5b7b8ac405e2ff65 Reviewed-on: https://go-review.googlesource.com/24815 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com>
Diffstat (limited to 'src/runtime/stack.go')
-rw-r--r--src/runtime/stack.go12
1 files changed, 10 insertions, 2 deletions
diff --git a/src/runtime/stack.go b/src/runtime/stack.go
index b14b4005d8..8398a101fd 100644
--- a/src/runtime/stack.go
+++ b/src/runtime/stack.go
@@ -784,8 +784,12 @@ func syncadjustsudogs(gp *g, used uintptr, adjinfo *adjustinfo) uintptr {
// copystack; otherwise, gp may be in the middle of
// putting itself on wait queues and this would
// self-deadlock.
+ var lastc *hchan
for sg := gp.waiting; sg != nil; sg = sg.waitlink {
- lock(&sg.c.lock)
+ if sg.c != lastc {
+ lock(&sg.c.lock)
+ }
+ lastc = sg.c
}
// Adjust sudogs.
@@ -803,8 +807,12 @@ func syncadjustsudogs(gp *g, used uintptr, adjinfo *adjustinfo) uintptr {
}
// Unlock channels.
+ lastc = nil
for sg := gp.waiting; sg != nil; sg = sg.waitlink {
- unlock(&sg.c.lock)
+ if sg.c != lastc {
+ unlock(&sg.c.lock)
+ }
+ lastc = sg.c
}
return sgsize