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>
diff --git a/src/runtime/proc1.go b/src/runtime/proc1.go
index a570816..35d9e86 100644
--- a/src/runtime/proc1.go
+++ b/src/runtime/proc1.go
@@ -988,6 +988,7 @@
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 @@
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 fbd43d2..7d3c8f6 100644
--- a/src/runtime/runtime2.go
+++ b/src/runtime/runtime2.go
@@ -229,6 +229,7 @@
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 9873bd8..78d168b 100644
--- a/src/runtime/stack1.go
+++ b/src/runtime/stack1.go
@@ -639,6 +639,7 @@
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 48ef6e5..1025032 100644
--- a/src/runtime/traceback.go
+++ b/src/runtime/traceback.go
@@ -479,6 +479,12 @@
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
}