components/golang/patches/0046-release-branch.go1.5-runtime-handle-sigprof-in-stack.patch
changeset 5331 9c955076ffe3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/golang/patches/0046-release-branch.go1.5-runtime-handle-sigprof-in-stack.patch	Thu Jan 21 09:20:59 2016 -0800
@@ -0,0 +1,70 @@
+From 2a6c7739b5bdb5fbaf743d89a18bd466fb178fe1 Mon Sep 17 00:00:00 2001
+From: Austin Clements <[email protected]>
+Date: Wed, 18 Nov 2015 13:20:35 -0500
+Subject: [PATCH 46/63] [release-branch.go1.5] runtime: handle sigprof in
+ stackBarrier
+
+Currently, if a profiling signal happens in the middle of
+stackBarrier, gentraceback may see inconsistencies between stkbar and
+the barriers on the stack and it will certainly get the wrong return
+PC for stackBarrier. In most cases, the return PC won't be a PC at all
+and this will immediately abort the traceback (which is considered
+okay for a sigprof), but if it happens to be a valid PC this may sent
+gentraceback down a rabbit hole.
+
+Fix this by detecting when the gentraceback starts in stackBarrier and
+simulating the completion of the barrier to get the correct initial
+frame.
+
+Change-Id: Ib11f705ac9194925f63fe5dfbfc84013a38333e6
+Reviewed-on: https://go-review.googlesource.com/17035
+Reviewed-by: Russ Cox <[email protected]>
+Run-TryBot: Austin Clements <[email protected]>
+TryBot-Result: Gobot Gobot <[email protected]>
+Reviewed-on: https://go-review.googlesource.com/17056
+---
+ src/runtime/traceback.go | 28 ++++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go
+index 2def359..aed6cbd 100644
+--- a/src/runtime/traceback.go
++++ b/src/runtime/traceback.go
+@@ -188,6 +188,34 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
+ 	}
+ 
+ 	f := findfunc(frame.pc)
++	if f.entry == stackBarrierPC {
++		// We got caught in the middle of a stack barrier
++		// (presumably by a signal), so stkbar may be
++		// inconsistent with the barriers on the stack.
++		// Simulate the completion of the barrier.
++		//
++		// On x86, SP will be exactly one word above
++		// savedLRPtr. On LR machines, SP will be above
++		// savedLRPtr by some frame size.
++		var stkbarPos uintptr
++		if len(stkbar) > 0 && stkbar[0].savedLRPtr < sp0 {
++			// stackBarrier has not incremented stkbarPos.
++			stkbarPos = gp.stkbarPos
++		} else if gp.stkbarPos > 0 && gp.stkbar[gp.stkbarPos-1].savedLRPtr < sp0 {
++			// stackBarrier has incremented stkbarPos.
++			stkbarPos = gp.stkbarPos - 1
++		} else {
++			printlock()
++			print("runtime: failed to unwind through stackBarrier at SP ", hex(sp0), " index ", gp.stkbarPos, "; ")
++			gcPrintStkbars(gp.stkbar)
++			print("\n")
++			throw("inconsistent state in stackBarrier")
++		}
++
++		frame.pc = gp.stkbar[stkbarPos].savedLRVal
++		stkbar = gp.stkbar[stkbarPos+1:]
++		f = findfunc(frame.pc)
++	}
+ 	if f == nil {
+ 		if callback != nil {
+ 			print("runtime: unknown pc ", hex(frame.pc), "\n")
+-- 
+2.6.1
+