]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: check explicitly for short unwinding of stacks
authorRuss Cox <rsc@golang.org>
Wed, 26 Aug 2015 15:39:10 +0000 (11:39 -0400)
committerRuss Cox <rsc@golang.org>
Fri, 28 Aug 2015 16:05:59 +0000 (16:05 +0000)
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>
src/runtime/proc1.go
src/runtime/runtime2.go
src/runtime/stack1.go
src/runtime/traceback.go

index a5708162de6bfdefe7e8f84c2d767bc38fc678df..35d9e86e8e8ab18bd8fce3abccbcca12b420ed87 100644 (file)
@@ -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)
index fbd43d21da628a5207cedf8bc085c1ea55f8a1dd..7d3c8f6aa2151ee06cb9f6a019f68bec62344bff 100644 (file)
@@ -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
index 9873bd860b43bdea3480b4b35a7f42abbdae1d64..78d168bb5bfe949a18216281fdae847b05ee7327 100644 (file)
@@ -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 {
index 48ef6e5e27f699b792996496a5e23ae1850c6f97..1025032aeecded0c2b2681f86004fdb664faa0a3 100644 (file)
@@ -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
 }