runtime: complete defer handling in CgocallBackDone
commit8e94e8f976826d17bf8cbcdcb83babdd2c60d28a
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 23 Jun 2017 20:19:40 +0000 (23 20:19 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 23 Jun 2017 20:19:40 +0000 (23 20:19 +0000)
tree19a34329dba9299efacbc2aaa92dce5f1108fe94
parent299d0f2388f98b2ba607e60a2bc9908b83fcc933
runtime: complete defer handling in CgocallBackDone

    When C code calls a Go function, it actually calls a function
    generated by cgo. That function is written in Go, and, among other
    things, it calls the real Go function like this:
            CgocallBack()
            defer CgocallBackDone()
            RealGoFunction()
    The deferred CgocallBackDone function enters syscall mode as we return
    to C. Typically the C function will then eventually return to Go.

    However, in the case where the C function is running on a thread
    created in C, it will not return to Go. For that case we will have
    allocated an m struct, with an associated g struct, for the duration
    of the Go code, and when the Go is complete we will return the m and g
    to a free list.

    That all works, but we are running in a deferred function, which means
    that we have been invoked by deferreturn, and deferreturn expects to
    do a bit of cleanup to record that the defer has been completed. Doing
    that cleanup while using an m and g that have already been returned to
    the free list is clearly a bad idea. It was kind of working because
    deferreturn was holding the g pointer in a local variable, but there
    were races with some other thread picking up and using the newly freed g.
    It was also kind of working because of a special check in freedefer;
    that check is no longer necessary.

    This patch changes the special case of releasing the m and g to do the
    defer cleanup in CgocallBackDone itself.

    This patch also checks for the special case of a panic through
    CgocallBackDone. In that special case, we don't want to release the m
    and g. Since we are returning to C code that was not called by Go
    code, we know that the panic is not going to be caught and we are
    going to exit the program. So for that special case we keep the m and
    g structs so that the rest of the panic code can use them.

    Reviewed-on: https://go-review.googlesource.com/46530

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@249611 138bc75d-0d04-0410-961f-82ee72b054a4
gcc/go/gofrontend/MERGE
libgo/go/runtime/cgo_gccgo.go
libgo/go/runtime/panic.go