github.com/huandu/go@v0.0.0-20151114150818-04e615e41150/test/fixedbugs/issue11656.go (about)

     1  // run
     2  
     3  // Copyright 2015 The Go Authors.  All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  // darwin/386 seems to mangle the PC and SP before
     8  // it manages to invoke the signal handler, so this test fails there.
     9  // +build !darwin !386
    10  //
    11  // openbsd/386 and netbsd/386 don't work, not sure why.
    12  // +build !openbsd !386
    13  // +build !netbsd !386
    14  //
    15  // windows doesn't work, because Windows exception handling
    16  // delivers signals based on the current PC, and that current PC
    17  // doesn't go into the Go runtime.
    18  // +build !windows
    19  //
    20  // arm64 gets "illegal instruction" (why is the data executable?)
    21  // and is unable to do the traceback correctly (why?).
    22  // +build !arm64
    23  
    24  package main
    25  
    26  import (
    27  	"runtime"
    28  	"runtime/debug"
    29  	"unsafe"
    30  )
    31  
    32  func main() {
    33  	debug.SetPanicOnFault(true)
    34  	defer func() {
    35  		if err := recover(); err == nil {
    36  			panic("not panicking")
    37  		}
    38  		pc, _, _, _ := runtime.Caller(10)
    39  		f := runtime.FuncForPC(pc)
    40  		if f == nil || f.Name() != "main.f" {
    41  			if f == nil {
    42  				println("no func for ", unsafe.Pointer(pc))
    43  			} else {
    44  				println("found func:", f.Name())
    45  			}
    46  			panic("cannot find main.f on stack")
    47  		}
    48  	}()
    49  	f(20)
    50  }
    51  
    52  func f(n int) {
    53  	if n > 0 {
    54  		f(n - 1)
    55  	}
    56  	var f struct {
    57  		x uintptr
    58  	}
    59  	f.x = uintptr(unsafe.Pointer(&f))
    60  	fn := *(*func())(unsafe.Pointer(&f))
    61  	fn()
    62  }