Commit e6708ee9 authored by Russ Cox's avatar Russ Cox

runtime: clear Defer.panic before removing from G.defer list

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
parent 3492ee5d
...@@ -34,6 +34,8 @@ runtime·deferproc_m(void) ...@@ -34,6 +34,8 @@ runtime·deferproc_m(void)
g->m->scalararg[1] = 0; g->m->scalararg[1] = 0;
d = runtime·newdefer(siz); d = runtime·newdefer(siz);
if(d->panic != nil)
runtime·throw("deferproc: d->panic != nil after newdefer");
d->fn = fn; d->fn = fn;
d->pc = callerpc; d->pc = callerpc;
d->argp = argp; d->argp = argp;
......
...@@ -188,6 +188,10 @@ func newdefer(siz int32) *_defer { ...@@ -188,6 +188,10 @@ func newdefer(siz int32) *_defer {
// The defer cannot be used after this call. // The defer cannot be used after this call.
//go:nosplit //go:nosplit
func freedefer(d *_defer) { 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)) sc := deferclass(uintptr(d.siz))
if sc < uintptr(len(p{}.deferpool)) { if sc < uintptr(len(p{}.deferpool)) {
mp := acquirem() mp := acquirem()
...@@ -258,6 +262,7 @@ func Goexit() { ...@@ -258,6 +262,7 @@ func Goexit() {
if d.started { if d.started {
if d._panic != nil { if d._panic != nil {
d._panic.aborted = true d._panic.aborted = true
d._panic = nil
} }
gp._defer = d.link gp._defer = d.link
freedefer(d) freedefer(d)
...@@ -268,6 +273,7 @@ func Goexit() { ...@@ -268,6 +273,7 @@ func Goexit() {
if gp._defer != d { if gp._defer != d {
gothrow("bad defer entry in Goexit") gothrow("bad defer entry in Goexit")
} }
d._panic = nil
gp._defer = d.link gp._defer = d.link
freedefer(d) freedefer(d)
// Note: we ignore recovers here because Goexit isn't a panic // Note: we ignore recovers here because Goexit isn't a panic
...@@ -343,6 +349,7 @@ func gopanic(e interface{}) { ...@@ -343,6 +349,7 @@ func gopanic(e interface{}) {
if d._panic != nil { if d._panic != nil {
d._panic.aborted = true d._panic.aborted = true
} }
d._panic = nil
gp._defer = d.link gp._defer = d.link
freedefer(d) freedefer(d)
continue continue
...@@ -366,6 +373,7 @@ func gopanic(e interface{}) { ...@@ -366,6 +373,7 @@ func gopanic(e interface{}) {
if gp._defer != d { if gp._defer != d {
gothrow("bad defer entry in panic") gothrow("bad defer entry in panic")
} }
d._panic = nil
gp._defer = d.link gp._defer = d.link
// trigger shrinkage to test stack copy. See stack_test.go:TestStackPanic // trigger shrinkage to test stack copy. See stack_test.go:TestStackPanic
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment