summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2015-08-26 11:39:10 -0400
committerRuss Cox <rsc@golang.org>2015-08-28 16:05:59 +0000
commit9c04d00214cb836ddcf4b7b6b0c4b4e5c11bb957 (patch)
treeeda2faf35b674f5692c1a3497d787271e91886a7
parent06b0f15e092ac8e7344f456875eb77d71fee93f8 (diff)
downloadgo-git-9c04d00214cb836ddcf4b7b6b0c4b4e5c11bb957.tar.gz
runtime: check explicitly for short unwinding of stacks
Right now we find out implicitly if stack barriers are in place, or defers. This change makes sure we find out about short unwinds always. Change-Id: Ibdde1ba9c79eb792660dcb7aa6f186e4e4d559b3 Reviewed-on: https://go-review.googlesource.com/13966 Reviewed-by: Austin Clements <austin@google.com>
-rw-r--r--src/runtime/proc1.go2
-rw-r--r--src/runtime/runtime2.go1
-rw-r--r--src/runtime/stack1.go1
-rw-r--r--src/runtime/traceback.go6
4 files changed, 10 insertions, 0 deletions
diff --git a/src/runtime/proc1.go b/src/runtime/proc1.go
index a5708162de..35d9e86e8e 100644
--- a/src/runtime/proc1.go
+++ b/src/runtime/proc1.go
@@ -988,6 +988,7 @@ func newextram() {
gp.sched.g = guintptr(unsafe.Pointer(gp))
gp.syscallpc = gp.sched.pc
gp.syscallsp = gp.sched.sp
+ gp.stktopsp = gp.sched.sp
// malg returns status as Gidle, change to Gsyscall before adding to allg
// where GC will see it.
casgstatus(gp, _Gidle, _Gsyscall)
@@ -2267,6 +2268,7 @@ func newproc1(fn *funcval, argp *uint8, narg int32, nret int32, callerpc uintptr
memclr(unsafe.Pointer(&newg.sched), unsafe.Sizeof(newg.sched))
newg.sched.sp = sp
+ newg.stktopsp = sp
newg.sched.pc = funcPC(goexit) + _PCQuantum // +PCQuantum so that previous instruction is in same function
newg.sched.g = guintptr(unsafe.Pointer(newg))
gostartcallfn(&newg.sched, fn)
diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go
index fbd43d21da..7d3c8f6aa2 100644
--- a/src/runtime/runtime2.go
+++ b/src/runtime/runtime2.go
@@ -229,6 +229,7 @@ type g struct {
syscallpc uintptr // if status==Gsyscall, syscallpc = sched.pc to use during gc
stkbar []stkbar // stack barriers, from low to high
stkbarPos uintptr // index of lowest stack barrier not hit
+ stktopsp uintptr // expected sp at top of stack, to check in traceback
param unsafe.Pointer // passed parameter on wakeup
atomicstatus uint32
stackLock uint32 // sigprof/scang lock; TODO: fold in to atomicstatus
diff --git a/src/runtime/stack1.go b/src/runtime/stack1.go
index 9873bd860b..78d168bb5b 100644
--- a/src/runtime/stack1.go
+++ b/src/runtime/stack1.go
@@ -639,6 +639,7 @@ func copystack(gp *g, newsize uintptr) {
oldsize := gp.stackAlloc
gp.stackAlloc = newsize
gp.stkbar = newstkbar
+ gp.stktopsp += adjinfo.delta
// free old stack
if stackPoisonCopy != 0 {
diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go
index 48ef6e5e27..1025032aee 100644
--- a/src/runtime/traceback.go
+++ b/src/runtime/traceback.go
@@ -479,6 +479,12 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
throw("traceback has leftover stack barriers")
}
+ if callback != nil && n < max && frame.sp != gp.stktopsp {
+ print("runtime: g", gp.goid, ": frame.sp=", hex(frame.sp), " top=", hex(gp.stktopsp), "\n")
+ print("\tstack=[", hex(gp.stack.lo), "-", hex(gp.stack.hi), "] n=", n, " max=", max, "\n")
+ throw("traceback did not unwind completely")
+ }
+
return n
}