From: Keith Randall Date: Mon, 15 Dec 2014 22:39:28 +0000 (-0800) Subject: [release-branch.go1.4] runtime: fix deadlock in runtime.Stack X-Git-Tag: go1.4.1~6 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=97b84fc4c86936ac0b012a7f091f70b1f791c11c;p=gostls13.git [release-branch.go1.4] runtime: fix deadlock in runtime.Stack It shouldn't semacquire() inside an acquirem(), the runtime thinks that means deadlock. It actually isn't a deadlock, but it looks like it because acquirem() does m.locks++. Candidate for inclusion in 1.4.1. runtime.Stack with all=true is pretty unuseable in GOMAXPROCS>1 environment. fixes #9321 Change-Id: Iac6b664217d24763b9878c20e49229a1ecffc805 Reviewed-on: https://go-review.googlesource.com/1600 Reviewed-by: Dmitry Vyukov (cherry picked from commit 50bc3d5bbc6710663c082aa72c8ba4f9ee515ab3) Reviewed-on: https://go-review.googlesource.com/2807 Reviewed-by: Andrew Gerrand --- diff --git a/src/runtime/mprof.go b/src/runtime/mprof.go index d409c6c306..f4da45f5c3 100644 --- a/src/runtime/mprof.go +++ b/src/runtime/mprof.go @@ -575,20 +575,16 @@ func saveg(pc, sp uintptr, gp *g, r *StackRecord) { // If all is true, Stack formats stack traces of all other goroutines // into buf after the trace for the current goroutine. func Stack(buf []byte, all bool) int { - mp := acquirem() - gp := mp.curg if all { semacquire(&worldsema, false) - mp.gcing = 1 - releasem(mp) + gp := getg() + gp.m.gcing = 1 onM(stoptheworld) - if mp != acquirem() { - gothrow("Stack: rescheduled") - } } n := 0 if len(buf) > 0 { + gp := getg() sp := getcallersp(unsafe.Pointer(&buf)) pc := getcallerpc(unsafe.Pointer(&buf)) onM(func() { @@ -605,11 +601,11 @@ func Stack(buf []byte, all bool) int { } if all { - mp.gcing = 0 + gp := getg() + gp.m.gcing = 0 semrelease(&worldsema) onM(starttheworld) } - releasem(mp) return n } diff --git a/test/fixedbugs/issue9321.go b/test/fixedbugs/issue9321.go new file mode 100644 index 0000000000..06cb5a6e36 --- /dev/null +++ b/test/fixedbugs/issue9321.go @@ -0,0 +1,37 @@ +// run + +// Copyright 2014 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. + +package main + +import ( + "bytes" + "runtime" + "runtime/pprof" + "sync" +) + +func test() { + var wg sync.WaitGroup + wg.Add(2) + test := func() { + for i := 0; i < 100; i++ { + buf := &bytes.Buffer{} + pprof.Lookup("goroutine").WriteTo(buf, 2) + } + wg.Done() + } + + go test() + go test() + wg.Wait() +} + +func main() { + runtime.GOMAXPROCS(2) + for i := 0; i < 100; i++ { + test() + } +}