diff options
Diffstat (limited to 'src/runtime')
| -rw-r--r-- | src/runtime/panic.go | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/src/runtime/panic.go b/src/runtime/panic.go index 58b14b09e3..685ff5ca0b 100644 --- a/src/runtime/panic.go +++ b/src/runtime/panic.go @@ -191,6 +191,9 @@ func freedefer(d *_defer) { if d._panic != nil { freedeferpanic() } + if d.fn != nil { + freedeferfn() + } sc := deferclass(uintptr(d.siz)) if sc < uintptr(len(p{}.deferpool)) { mp := acquirem() @@ -209,6 +212,11 @@ func freedeferpanic() { gothrow("freedefer with d._panic != nil") } +func freedeferfn() { + // fn must be cleared before d is unlinked from gp. + gothrow("freedefer with d.fn != nil") +} + // Run a deferred function if there is one. // The compiler inserts a call to this at the end of any // function which calls defer. @@ -241,6 +249,7 @@ func deferreturn(arg0 uintptr) { mp := acquirem() memmove(unsafe.Pointer(argp), deferArgs(d), uintptr(d.siz)) fn := d.fn + d.fn = nil gp._defer = d.link freedefer(d) releasem(mp) @@ -270,6 +279,7 @@ func Goexit() { d._panic.aborted = true d._panic = nil } + d.fn = nil gp._defer = d.link freedefer(d) continue @@ -280,6 +290,7 @@ func Goexit() { gothrow("bad defer entry in Goexit") } d._panic = nil + d.fn = nil gp._defer = d.link freedefer(d) // Note: we ignore recovers here because Goexit isn't a panic @@ -356,6 +367,7 @@ func gopanic(e interface{}) { d._panic.aborted = true } d._panic = nil + d.fn = nil gp._defer = d.link freedefer(d) continue @@ -380,6 +392,7 @@ func gopanic(e interface{}) { gothrow("bad defer entry in panic") } d._panic = nil + d.fn = nil gp._defer = d.link // trigger shrinkage to test stack copy. See stack_test.go:TestStackPanic |
