aboutsummaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2016-12-08 15:54:30 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2016-12-08 15:54:30 +0000
commitb2264b0964560e724010aac2faf4f6a3ec2729f7 (patch)
tree6975dcd13003606feee2cb8d7753ef271c391a97 /libgo
parent0a7577bbac00ea3ecfa8f25d38c98ea696f3a0ce (diff)
downloadgcc-b2264b0964560e724010aac2faf4f6a3ec2729f7.zip
gcc-b2264b0964560e724010aac2faf4f6a3ec2729f7.tar.gz
gcc-b2264b0964560e724010aac2faf4f6a3ec2729f7.tar.bz2
runtime: allocate _panic struct on heap
The gc library allocates a _panic struct on the stack. This does not work for gccgo, because when a deferred function recovers the panic we unwind the stack up to that point so that returning from the function will work correctly. Allocating on the stack fine if the panic is not recovered, and it works fine if the panic is recovered by a function that returns. However, it fails if the panic is recovered by a function that itself panics, and if that second panic is then recovered by a function higher up on the stack. When we unwind the stack to that second panic, the g will wind up pointing at a panic farther down on the stack. Even then everything will often work fine, except when the deferred function catching the second panic makes a bunch of calls that use stack space before returning. In that case the code can overwrite the panic struct, which will then cause disaster when we remove the struct from the linked list, as the link field will be garbage. This case is rare enough that all the x86 tests were passing, but there was a failure on ppc64le. Before https://golang.org/cl/33414 we allocated the panic struct on the heap, so go back to doing that again. Fixes golang/go#18228. Reviewed-on: https://go-review.googlesource.com/34027 From-SVN: r243444
Diffstat (limited to 'libgo')
-rw-r--r--libgo/go/runtime/panic.go17
1 files changed, 13 insertions, 4 deletions
diff --git a/libgo/go/runtime/panic.go b/libgo/go/runtime/panic.go
index 0ad178f..f7e5efe 100644
--- a/libgo/go/runtime/panic.go
+++ b/libgo/go/runtime/panic.go
@@ -415,10 +415,19 @@ func gopanic(e interface{}) {
throw("panic holding locks")
}
- var p _panic
- p.arg = e
- p.link = gp._panic
- gp._panic = (*_panic)(noescape(unsafe.Pointer(&p)))
+ // The gc compiler allocates this new _panic struct on the
+ // stack. We can't do that, because when a deferred function
+ // recovers the panic we unwind the stack. We unlink this
+ // entry before unwinding the stack, but that doesn't help in
+ // the case where we panic, a deferred function recovers and
+ // then panics itself, that panic is in turn recovered, and
+ // unwinds the stack past this stack frame.
+
+ p := &_panic{
+ arg: e,
+ link: gp._panic,
+ }
+ gp._panic = p
for {
d := gp._defer