mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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
This commit is contained in:
parent
3492ee5d3a
commit
e6708ee9b1
2 changed files with 10 additions and 0 deletions
|
|
@ -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 {
|
||||||
// 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() {
|
||||||
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() {
|
||||||
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{}) {
|
||||||
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{}) {
|
||||||
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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue