]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: clear Defer.panic before removing from G.defer list
authorRuss Cox <rsc@golang.org>
Wed, 8 Oct 2014 03:17:31 +0000 (23:17 -0400)
committerRuss Cox <rsc@golang.org>
Wed, 8 Oct 2014 03:17:31 +0000 (23:17 -0400)
Another dangling stack pointer in a cached structure.
Same as SudoG.elem and SudoG.selectdone.

Definitely a fix, and the new test in freedefer makes the
crash reproducible, but probably not a complete fix.
I have seen one dangling pointer in a Defer.panic even
after this fix; I cannot see where it could be coming from.

I think this will fix the solaris build.
I do not think this will fix the occasional failure on the darwin build.

TBR=khr
R=khr
CC=golang-codereviews
https://golang.org/cl/155080043

src/runtime/panic.c
src/runtime/panic.go

index 55ad80e9bcd36bbb1392d243bca0eba03295b8c3..24eb6dbfe0887872e2c8e52709839a4c1cb79f45 100644 (file)
@@ -34,6 +34,8 @@ runtime·deferproc_m(void)
        g->m->scalararg[1] = 0;
 
        d = runtime·newdefer(siz);
+       if(d->panic != nil)
+               runtime·throw("deferproc: d->panic != nil after newdefer");
        d->fn = fn;
        d->pc = callerpc;
        d->argp = argp;
index 7eb2d6055a82c2f299a593cb22c566f5a57a95cd..c78102f8a30ffb43858ee802afadbcf994160f57 100644 (file)
@@ -188,6 +188,10 @@ func newdefer(siz int32) *_defer {
 // The defer cannot be used after this call.
 //go:nosplit
 func freedefer(d *_defer) {
+       if d._panic != nil {
+               // _panic must be cleared before d is unlinked from gp.
+               gothrow("freedefer with d._panic != nil")
+       }
        sc := deferclass(uintptr(d.siz))
        if sc < uintptr(len(p{}.deferpool)) {
                mp := acquirem()
@@ -258,6 +262,7 @@ func Goexit() {
                if d.started {
                        if d._panic != nil {
                                d._panic.aborted = true
+                               d._panic = nil
                        }
                        gp._defer = d.link
                        freedefer(d)
@@ -268,6 +273,7 @@ func Goexit() {
                if gp._defer != d {
                        gothrow("bad defer entry in Goexit")
                }
+               d._panic = nil
                gp._defer = d.link
                freedefer(d)
                // Note: we ignore recovers here because Goexit isn't a panic
@@ -343,6 +349,7 @@ func gopanic(e interface{}) {
                        if d._panic != nil {
                                d._panic.aborted = true
                        }
+                       d._panic = nil
                        gp._defer = d.link
                        freedefer(d)
                        continue
@@ -366,6 +373,7 @@ func gopanic(e interface{}) {
                if gp._defer != d {
                        gothrow("bad defer entry in panic")
                }
+               d._panic = nil
                gp._defer = d.link
 
                // trigger shrinkage to test stack copy.  See stack_test.go:TestStackPanic