runtime: allocate _panic struct on heap
authorIan Lance Taylor <ian@gcc.gnu.org>
Thu, 8 Dec 2016 15:54:30 +0000 (15:54 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Thu, 8 Dec 2016 15:54:30 +0000 (15:54 +0000)
    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

gcc/go/gofrontend/MERGE
libgo/go/runtime/panic.go

index dbba68fb26058e9c86c4c707a5ca1c09eb4733b8..df38903801645e873194be0d979ad798d51a3dc5 100644 (file)
@@ -1,4 +1,4 @@
-7a941ba323660ec7034cd92d4eab466024a3c72c
+2442fca7be8a4f51ddc91070fa69ef66e24593ac
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index 0ad178f45f61dce669d492ac00aac19302b6a4ef..f7e5efe363e0a6fd035ccbc13ac79691ee4a21da 100644 (file)
@@ -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