|  | // Copyright 2014 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package runtime | 
|  |  | 
|  | import ( | 
|  | "runtime/internal/atomic" | 
|  | "unsafe" | 
|  | ) | 
|  |  | 
|  | // For gccgo, use go:linkname to rename compiler-called functions to | 
|  | // themselves, so that the compiler will export them. | 
|  | // | 
|  | //go:linkname deferproc runtime.deferproc | 
|  | //go:linkname deferreturn runtime.deferreturn | 
|  | //go:linkname setdeferretaddr runtime.setdeferretaddr | 
|  | //go:linkname checkdefer runtime.checkdefer | 
|  | //go:linkname gopanic runtime.gopanic | 
|  | //go:linkname canrecover runtime.canrecover | 
|  | //go:linkname makefuncfficanrecover runtime.makefuncfficanrecover | 
|  | //go:linkname makefuncreturning runtime.makefuncreturning | 
|  | //go:linkname gorecover runtime.gorecover | 
|  | //go:linkname deferredrecover runtime.deferredrecover | 
|  | //go:linkname panicmem runtime.panicmem | 
|  | // Temporary for C code to call: | 
|  | //go:linkname throw runtime.throw | 
|  |  | 
|  | // Calling panic with one of the errors below will call errorString.Error | 
|  | // which will call mallocgc to concatenate strings. That will fail if | 
|  | // malloc is locked, causing a confusing error message. Throw a better | 
|  | // error message instead. | 
|  | func panicCheckMalloc(err error) { | 
|  | gp := getg() | 
|  | if gp != nil && gp.m != nil && gp.m.mallocing != 0 { | 
|  | throw(string(err.(errorString))) | 
|  | } | 
|  | } | 
|  |  | 
|  | var indexError = error(errorString("index out of range")) | 
|  |  | 
|  | // The panicindex, panicslice, and panicdivide functions are called by | 
|  | // code generated by the compiler for out of bounds index expressions, | 
|  | // out of bounds slice expressions, and division by zero. The | 
|  | // panicdivide (again), panicoverflow, panicfloat, and panicmem | 
|  | // functions are called by the signal handler when a signal occurs | 
|  | // indicating the respective problem. | 
|  | // | 
|  | // Since panicindex and panicslice are never called directly, and | 
|  | // since the runtime package should never have an out of bounds slice | 
|  | // or array reference, if we see those functions called from the | 
|  | // runtime package we turn the panic into a throw. That will dump the | 
|  | // entire runtime stack for easier debugging. | 
|  |  | 
|  | func panicindex() { | 
|  | name, _, _ := funcfileline(getcallerpc()-1, -1) | 
|  | if hasPrefix(name, "runtime.") { | 
|  | throw(string(indexError.(errorString))) | 
|  | } | 
|  | panicCheckMalloc(indexError) | 
|  | panic(indexError) | 
|  | } | 
|  |  | 
|  | var sliceError = error(errorString("slice bounds out of range")) | 
|  |  | 
|  | func panicslice() { | 
|  | name, _, _ := funcfileline(getcallerpc()-1, -1) | 
|  | if hasPrefix(name, "runtime.") { | 
|  | throw(string(sliceError.(errorString))) | 
|  | } | 
|  | panicCheckMalloc(sliceError) | 
|  | panic(sliceError) | 
|  | } | 
|  |  | 
|  | var divideError = error(errorString("integer divide by zero")) | 
|  |  | 
|  | func panicdivide() { | 
|  | panicCheckMalloc(divideError) | 
|  | panic(divideError) | 
|  | } | 
|  |  | 
|  | var overflowError = error(errorString("integer overflow")) | 
|  |  | 
|  | func panicoverflow() { | 
|  | panicCheckMalloc(overflowError) | 
|  | panic(overflowError) | 
|  | } | 
|  |  | 
|  | var floatError = error(errorString("floating point error")) | 
|  |  | 
|  | func panicfloat() { | 
|  | panicCheckMalloc(floatError) | 
|  | panic(floatError) | 
|  | } | 
|  |  | 
|  | var memoryError = error(errorString("invalid memory address or nil pointer dereference")) | 
|  |  | 
|  | func panicmem() { | 
|  | panicCheckMalloc(memoryError) | 
|  | panic(memoryError) | 
|  | } | 
|  |  | 
|  | func throwinit() { | 
|  | throw("recursive call during initialization - linker skew") | 
|  | } | 
|  |  | 
|  | // deferproc creates a new deferred function. | 
|  | // The compiler turns a defer statement into a call to this. | 
|  | // frame points into the stack frame; it is used to determine which | 
|  | // deferred functions are for the current stack frame, and whether we | 
|  | // have already deferred functions for this frame. | 
|  | // pfn is a C function pointer. | 
|  | // arg is a value to pass to pfn. | 
|  | func deferproc(frame *bool, pfn uintptr, arg unsafe.Pointer) { | 
|  | d := newdefer() | 
|  | if d._panic != nil { | 
|  | throw("deferproc: d.panic != nil after newdefer") | 
|  | } | 
|  | d.frame = frame | 
|  | d.panicStack = getg()._panic | 
|  | d.pfn = pfn | 
|  | d.arg = arg | 
|  | d.retaddr = 0 | 
|  | d.makefunccanrecover = false | 
|  | } | 
|  |  | 
|  | // Allocate a Defer, usually using per-P pool. | 
|  | // Each defer must be released with freedefer. | 
|  | func newdefer() *_defer { | 
|  | var d *_defer | 
|  | gp := getg() | 
|  | pp := gp.m.p.ptr() | 
|  | if len(pp.deferpool) == 0 && sched.deferpool != nil { | 
|  | systemstack(func() { | 
|  | lock(&sched.deferlock) | 
|  | for len(pp.deferpool) < cap(pp.deferpool)/2 && sched.deferpool != nil { | 
|  | d := sched.deferpool | 
|  | sched.deferpool = d.link | 
|  | d.link = nil | 
|  | pp.deferpool = append(pp.deferpool, d) | 
|  | } | 
|  | unlock(&sched.deferlock) | 
|  | }) | 
|  | } | 
|  | if n := len(pp.deferpool); n > 0 { | 
|  | d = pp.deferpool[n-1] | 
|  | pp.deferpool[n-1] = nil | 
|  | pp.deferpool = pp.deferpool[:n-1] | 
|  | } | 
|  | if d == nil { | 
|  | systemstack(func() { | 
|  | d = new(_defer) | 
|  | }) | 
|  | if debugCachedWork { | 
|  | // Duplicate the tail below so if there's a | 
|  | // crash in checkPut we can tell if d was just | 
|  | // allocated or came from the pool. | 
|  | d.link = gp._defer | 
|  | gp._defer = d | 
|  | return d | 
|  | } | 
|  | } | 
|  | d.link = gp._defer | 
|  | gp._defer = d | 
|  | return d | 
|  | } | 
|  |  | 
|  | // Free the given defer. | 
|  | // The defer cannot be used after this call. | 
|  | // | 
|  | // This must not grow the stack because there may be a frame without a | 
|  | // stack map when this is called. | 
|  | // | 
|  | //go:nosplit | 
|  | func freedefer(d *_defer) { | 
|  | if d._panic != nil { | 
|  | freedeferpanic() | 
|  | } | 
|  | if d.pfn != 0 { | 
|  | freedeferfn() | 
|  | } | 
|  | pp := getg().m.p.ptr() | 
|  | if len(pp.deferpool) == cap(pp.deferpool) { | 
|  | // Transfer half of local cache to the central cache. | 
|  | // | 
|  | // Take this slow path on the system stack so | 
|  | // we don't grow freedefer's stack. | 
|  | systemstack(func() { | 
|  | var first, last *_defer | 
|  | for len(pp.deferpool) > cap(pp.deferpool)/2 { | 
|  | n := len(pp.deferpool) | 
|  | d := pp.deferpool[n-1] | 
|  | pp.deferpool[n-1] = nil | 
|  | pp.deferpool = pp.deferpool[:n-1] | 
|  | if first == nil { | 
|  | first = d | 
|  | } else { | 
|  | last.link = d | 
|  | } | 
|  | last = d | 
|  | } | 
|  | lock(&sched.deferlock) | 
|  | last.link = sched.deferpool | 
|  | sched.deferpool = first | 
|  | unlock(&sched.deferlock) | 
|  | }) | 
|  | } | 
|  |  | 
|  | // These lines used to be simply `*d = _defer{}` but that | 
|  | // started causing a nosplit stack overflow via typedmemmove. | 
|  | d.link = nil | 
|  | d.frame = nil | 
|  | d.panicStack = nil | 
|  | d.arg = nil | 
|  | d.retaddr = 0 | 
|  | d.makefunccanrecover = false | 
|  | // d._panic and d.pfn must be nil already. | 
|  | // If not, we would have called freedeferpanic or freedeferfn above, | 
|  | // both of which throw. | 
|  |  | 
|  | pp.deferpool = append(pp.deferpool, d) | 
|  | } | 
|  |  | 
|  | // Separate function so that it can split stack. | 
|  | // Windows otherwise runs out of stack space. | 
|  | func freedeferpanic() { | 
|  | // _panic must be cleared before d is unlinked from gp. | 
|  | throw("freedefer with d._panic != nil") | 
|  | } | 
|  |  | 
|  | func freedeferfn() { | 
|  | // fn must be cleared before d is unlinked from gp. | 
|  | throw("freedefer with d.fn != nil") | 
|  | } | 
|  |  | 
|  | // deferreturn is called to undefer the stack. | 
|  | // The compiler inserts a call to this function as a finally clause | 
|  | // wrapped around the body of any function that calls defer. | 
|  | // The frame argument points to the stack frame of the function. | 
|  | func deferreturn(frame *bool) { | 
|  | gp := getg() | 
|  | for gp._defer != nil && gp._defer.frame == frame { | 
|  | d := gp._defer | 
|  | pfn := d.pfn | 
|  | d.pfn = 0 | 
|  |  | 
|  | if pfn != 0 { | 
|  | // This is rather awkward. | 
|  | // The gc compiler does this using assembler | 
|  | // code in jmpdefer. | 
|  | var fn func(unsafe.Pointer) | 
|  | *(*uintptr)(unsafe.Pointer(&fn)) = uintptr(noescape(unsafe.Pointer(&pfn))) | 
|  | gp.deferring = true | 
|  | fn(d.arg) | 
|  | gp.deferring = false | 
|  | } | 
|  |  | 
|  | // If that was CgocallBackDone, it will have freed the | 
|  | // defer for us, since we are no longer running as Go code. | 
|  | if getg() == nil { | 
|  | *frame = true | 
|  | return | 
|  | } | 
|  | if gp.ranCgocallBackDone { | 
|  | gp.ranCgocallBackDone = false | 
|  | *frame = true | 
|  | return | 
|  | } | 
|  |  | 
|  | gp._defer = d.link | 
|  |  | 
|  | freedefer(d) | 
|  |  | 
|  | // Since we are executing a defer function now, we | 
|  | // know that we are returning from the calling | 
|  | // function. If the calling function, or one of its | 
|  | // callees, panicked, then the defer functions would | 
|  | // be executed by panic. | 
|  | *frame = true | 
|  | } | 
|  | } | 
|  |  | 
|  | // __builtin_extract_return_addr is a GCC intrinsic that converts an | 
|  | // address returned by __builtin_return_address(0) to a real address. | 
|  | // On most architectures this is a nop. | 
|  | //extern __builtin_extract_return_addr | 
|  | func __builtin_extract_return_addr(uintptr) uintptr | 
|  |  | 
|  | // setdeferretaddr records the address to which the deferred function | 
|  | // returns.  This is check by canrecover.  The frontend relies on this | 
|  | // function returning false. | 
|  | func setdeferretaddr(retaddr uintptr) bool { | 
|  | gp := getg() | 
|  | if gp._defer != nil { | 
|  | gp._defer.retaddr = __builtin_extract_return_addr(retaddr) | 
|  | } | 
|  | return false | 
|  | } | 
|  |  | 
|  | // checkdefer is called by exception handlers used when unwinding the | 
|  | // stack after a recovered panic. The exception handler is simply | 
|  | //   checkdefer(frame) | 
|  | //   return; | 
|  | // If we have not yet reached the frame we are looking for, we | 
|  | // continue unwinding. | 
|  | func checkdefer(frame *bool) { | 
|  | gp := getg() | 
|  | if gp == nil { | 
|  | // We should never wind up here. Even if some other | 
|  | // language throws an exception, the cgo code | 
|  | // should ensure that g is set. | 
|  | throw("no g in checkdefer") | 
|  | } else if gp.isforeign { | 
|  | // Some other language has thrown an exception. | 
|  | // We need to run the local defer handlers. | 
|  | // If they call recover, we stop unwinding here. | 
|  | var p _panic | 
|  | p.isforeign = true | 
|  | p.link = gp._panic | 
|  | gp._panic = (*_panic)(noescape(unsafe.Pointer(&p))) | 
|  | for { | 
|  | d := gp._defer | 
|  | if d == nil || d.frame != frame || d.pfn == 0 { | 
|  | break | 
|  | } | 
|  |  | 
|  | pfn := d.pfn | 
|  | gp._defer = d.link | 
|  |  | 
|  | var fn func(unsafe.Pointer) | 
|  | *(*uintptr)(unsafe.Pointer(&fn)) = uintptr(noescape(unsafe.Pointer(&pfn))) | 
|  | gp.deferring = true | 
|  | fn(d.arg) | 
|  | gp.deferring = false | 
|  |  | 
|  | freedefer(d) | 
|  |  | 
|  | if p.recovered { | 
|  | // The recover function caught the panic | 
|  | // thrown by some other language. | 
|  | break | 
|  | } | 
|  | } | 
|  |  | 
|  | recovered := p.recovered | 
|  | gp._panic = p.link | 
|  |  | 
|  | if recovered { | 
|  | // Just return and continue executing Go code. | 
|  | *frame = true | 
|  | return | 
|  | } | 
|  |  | 
|  | // We are panicking through this function. | 
|  | *frame = false | 
|  | } else if gp._defer != nil && gp._defer.pfn == 0 && gp._defer.frame == frame { | 
|  | // This is the defer function that called recover. | 
|  | // Simply return to stop the stack unwind, and let the | 
|  | // Go code continue to execute. | 
|  | d := gp._defer | 
|  | gp._defer = d.link | 
|  | freedefer(d) | 
|  |  | 
|  | // We are returning from this function. | 
|  | *frame = true | 
|  |  | 
|  | return | 
|  | } | 
|  |  | 
|  | // This is some other defer function. It was already run by | 
|  | // the call to panic, or just above. Rethrow the exception. | 
|  | rethrowException() | 
|  | throw("rethrowException returned") | 
|  | } | 
|  |  | 
|  | // unwindStack starts unwinding the stack for a panic. We unwind | 
|  | // function calls until we reach the one which used a defer function | 
|  | // which called recover. Each function which uses a defer statement | 
|  | // will have an exception handler, as shown above for checkdefer. | 
|  | func unwindStack() { | 
|  | // Allocate the exception type used by the unwind ABI. | 
|  | // It would be nice to define it in runtime_sysinfo.go, | 
|  | // but current definitions don't work because the required | 
|  | // alignment is larger than can be represented in Go. | 
|  | // The type never contains any Go pointers. | 
|  | size := unwindExceptionSize() | 
|  | usize := uintptr(unsafe.Sizeof(uintptr(0))) | 
|  | c := (size + usize - 1) / usize | 
|  | s := make([]uintptr, c) | 
|  | getg().exception = unsafe.Pointer(&s[0]) | 
|  | throwException() | 
|  | } | 
|  |  | 
|  | // Goexit terminates the goroutine that calls it. No other goroutine is affected. | 
|  | // Goexit runs all deferred calls before terminating the goroutine. Because Goexit | 
|  | // is not a panic, any recover calls in those deferred functions will return nil. | 
|  | // | 
|  | // Calling Goexit from the main goroutine terminates that goroutine | 
|  | // without func main returning. Since func main has not returned, | 
|  | // the program continues execution of other goroutines. | 
|  | // If all other goroutines exit, the program crashes. | 
|  | func Goexit() { | 
|  | // Run all deferred functions for the current goroutine. | 
|  | // This code is similar to gopanic, see that implementation | 
|  | // for detailed comments. | 
|  | gp := getg() | 
|  | gp.goexiting = true | 
|  | for { | 
|  | d := gp._defer | 
|  | if d == nil { | 
|  | break | 
|  | } | 
|  |  | 
|  | pfn := d.pfn | 
|  | if pfn == 0 { | 
|  | if d._panic != nil { | 
|  | d._panic.aborted = true | 
|  | d._panic = nil | 
|  | } | 
|  | gp._defer = d.link | 
|  | freedefer(d) | 
|  | continue | 
|  | } | 
|  | d.pfn = 0 | 
|  |  | 
|  | var fn func(unsafe.Pointer) | 
|  | *(*uintptr)(unsafe.Pointer(&fn)) = uintptr(noescape(unsafe.Pointer(&pfn))) | 
|  | gp.deferring = true | 
|  | fn(d.arg) | 
|  | gp.deferring = false | 
|  |  | 
|  | if gp._defer != d { | 
|  | throw("bad defer entry in Goexit") | 
|  | } | 
|  | d._panic = nil | 
|  | gp._defer = d.link | 
|  | freedefer(d) | 
|  | // Note: we ignore recovers here because Goexit isn't a panic | 
|  | } | 
|  | gp.goexiting = false | 
|  | goexit1() | 
|  | } | 
|  |  | 
|  | // Call all Error and String methods before freezing the world. | 
|  | // Used when crashing with panicking. | 
|  | func preprintpanics(p *_panic) { | 
|  | defer func() { | 
|  | if recover() != nil { | 
|  | throw("panic while printing panic value") | 
|  | } | 
|  | }() | 
|  | for p != nil { | 
|  | switch v := p.arg.(type) { | 
|  | case error: | 
|  | p.arg = v.Error() | 
|  | case stringer: | 
|  | p.arg = v.String() | 
|  | } | 
|  | p = p.link | 
|  | } | 
|  | } | 
|  |  | 
|  | // Print all currently active panics. Used when crashing. | 
|  | // Should only be called after preprintpanics. | 
|  | func printpanics(p *_panic) { | 
|  | if p.link != nil { | 
|  | printpanics(p.link) | 
|  | print("\t") | 
|  | } | 
|  | print("panic: ") | 
|  | printany(p.arg) | 
|  | if p.recovered { | 
|  | print(" [recovered]") | 
|  | } | 
|  | print("\n") | 
|  | } | 
|  |  | 
|  | // The implementation of the predeclared function panic. | 
|  | func gopanic(e interface{}) { | 
|  | gp := getg() | 
|  | if gp.m.curg != gp { | 
|  | print("panic: ") | 
|  | printany(e) | 
|  | print("\n") | 
|  | throw("panic on system stack") | 
|  | } | 
|  |  | 
|  | if gp.m.mallocing != 0 { | 
|  | print("panic: ") | 
|  | printany(e) | 
|  | print("\n") | 
|  | throw("panic during malloc") | 
|  | } | 
|  | if gp.m.preemptoff != "" { | 
|  | print("panic: ") | 
|  | printany(e) | 
|  | print("\n") | 
|  | print("preempt off reason: ") | 
|  | print(gp.m.preemptoff) | 
|  | print("\n") | 
|  | throw("panic during preemptoff") | 
|  | } | 
|  | if gp.m.locks != 0 { | 
|  | print("panic: ") | 
|  | printany(e) | 
|  | print("\n") | 
|  | throw("panic holding locks") | 
|  | } | 
|  |  | 
|  | // 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 | 
|  |  | 
|  | atomic.Xadd(&runningPanicDefers, 1) | 
|  |  | 
|  | for { | 
|  | d := gp._defer | 
|  | if d == nil { | 
|  | break | 
|  | } | 
|  |  | 
|  | pfn := d.pfn | 
|  |  | 
|  | // If defer was started by earlier panic or Goexit (and, since we're back here, that triggered a new panic), | 
|  | // take defer off list. The earlier panic or Goexit will not continue running. | 
|  | if pfn == 0 { | 
|  | if d._panic != nil { | 
|  | d._panic.aborted = true | 
|  | } | 
|  | d._panic = nil | 
|  | gp._defer = d.link | 
|  | freedefer(d) | 
|  | continue | 
|  | } | 
|  | d.pfn = 0 | 
|  |  | 
|  | // Record the panic that is running the defer. | 
|  | // If there is a new panic during the deferred call, that panic | 
|  | // will find d in the list and will mark d._panic (this panic) aborted. | 
|  | d._panic = p | 
|  |  | 
|  | var fn func(unsafe.Pointer) | 
|  | *(*uintptr)(unsafe.Pointer(&fn)) = uintptr(noescape(unsafe.Pointer(&pfn))) | 
|  | gp.deferring = true | 
|  | fn(d.arg) | 
|  | gp.deferring = false | 
|  |  | 
|  | if gp._defer != d { | 
|  | throw("bad defer entry in panic") | 
|  | } | 
|  | d._panic = nil | 
|  |  | 
|  | if p.recovered { | 
|  | atomic.Xadd(&runningPanicDefers, -1) | 
|  |  | 
|  | gp._panic = p.link | 
|  |  | 
|  | // Aborted panics are marked but remain on the g.panic list. | 
|  | // Remove them from the list. | 
|  | for gp._panic != nil && gp._panic.aborted { | 
|  | gp._panic = gp._panic.link | 
|  | } | 
|  | if gp._panic == nil { // must be done with signal | 
|  | gp.sig = 0 | 
|  | } | 
|  |  | 
|  | // Unwind the stack by throwing an exception. | 
|  | // The compiler has arranged to create | 
|  | // exception handlers in each function | 
|  | // that uses a defer statement.  These | 
|  | // exception handlers will check whether | 
|  | // the entry on the top of the defer stack | 
|  | // is from the current function.  If it is, | 
|  | // we have unwound the stack far enough. | 
|  | unwindStack() | 
|  |  | 
|  | throw("unwindStack returned") | 
|  | } | 
|  |  | 
|  | // Because we executed that defer function by a panic, | 
|  | // and it did not call recover, we know that we are | 
|  | // not returning from the calling function--we are | 
|  | // panicking through it. | 
|  | *d.frame = false | 
|  |  | 
|  | // Deferred function did not panic. Remove d. | 
|  | // In the p.recovered case, d will be removed by checkdefer. | 
|  | gp._defer = d.link | 
|  |  | 
|  | freedefer(d) | 
|  | } | 
|  |  | 
|  | // ran out of deferred calls - old-school panic now | 
|  | // Because it is unsafe to call arbitrary user code after freezing | 
|  | // the world, we call preprintpanics to invoke all necessary Error | 
|  | // and String methods to prepare the panic strings before startpanic. | 
|  | preprintpanics(gp._panic) | 
|  |  | 
|  | fatalpanic(gp._panic) // should not return | 
|  | *(*int)(nil) = 0      // not reached | 
|  | } | 
|  |  | 
|  | // currentDefer returns the top of the defer stack if it can be recovered. | 
|  | // Otherwise it returns nil. | 
|  | func currentDefer() *_defer { | 
|  | gp := getg() | 
|  | d := gp._defer | 
|  | if d == nil { | 
|  | return nil | 
|  | } | 
|  |  | 
|  | // The panic that would be recovered is the one on the top of | 
|  | // the panic stack. We do not want to recover it if that panic | 
|  | // was on the top of the panic stack when this function was | 
|  | // deferred. | 
|  | if d.panicStack == gp._panic { | 
|  | return nil | 
|  | } | 
|  |  | 
|  | // The deferred thunk will call setdeferretaddr. If this has | 
|  | // not happened, then we have not been called via defer, and | 
|  | // we can not recover. | 
|  | if d.retaddr == 0 { | 
|  | return nil | 
|  | } | 
|  |  | 
|  | return d | 
|  | } | 
|  |  | 
|  | // canrecover is called by a thunk to see if the real function would | 
|  | // be permitted to recover a panic value. Recovering a value is | 
|  | // permitted if the thunk was called directly by defer. retaddr is the | 
|  | // return address of the function that is calling canrecover--that is, | 
|  | // the thunk. | 
|  | func canrecover(retaddr uintptr) bool { | 
|  | d := currentDefer() | 
|  | if d == nil { | 
|  | return false | 
|  | } | 
|  |  | 
|  | ret := __builtin_extract_return_addr(retaddr) | 
|  | dret := d.retaddr | 
|  | if ret <= dret && ret+16 >= dret { | 
|  | return true | 
|  | } | 
|  |  | 
|  | // On some systems, in some cases, the return address does not | 
|  | // work reliably. See http://gcc.gnu.org/PR60406. If we are | 
|  | // permitted to call recover, the call stack will look like this: | 
|  | //     runtime.gopanic, runtime.deferreturn, etc. | 
|  | //     thunk to call deferred function (calls __go_set_defer_retaddr) | 
|  | //     function that calls __go_can_recover (passing return address) | 
|  | //     runtime.canrecover | 
|  | // Calling callers will skip the thunks. So if our caller's | 
|  | // caller starts with "runtime.", then we are permitted to | 
|  | // call recover. | 
|  | var locs [16]location | 
|  | if callers(1, locs[:2]) < 2 { | 
|  | return false | 
|  | } | 
|  |  | 
|  | name := locs[1].function | 
|  | if hasPrefix(name, "runtime.") { | 
|  | return true | 
|  | } | 
|  |  | 
|  | // If the function calling recover was created by reflect.MakeFunc, | 
|  | // then makefuncfficanrecover will have set makefunccanrecover. | 
|  | if !d.makefunccanrecover { | 
|  | return false | 
|  | } | 
|  |  | 
|  | // We look up the stack, ignoring libffi functions and | 
|  | // functions in the reflect package, until we find | 
|  | // reflect.makeFuncStub or reflect.ffi_callback called by FFI | 
|  | // functions.  Then we check the caller of that function. | 
|  |  | 
|  | n := callers(2, locs[:]) | 
|  | foundFFICallback := false | 
|  | i := 0 | 
|  | for ; i < n; i++ { | 
|  | name = locs[i].function | 
|  | if name == "" { | 
|  | // No function name means this caller isn't Go code. | 
|  | // Assume that this is libffi. | 
|  | continue | 
|  | } | 
|  |  | 
|  | // Ignore function in libffi. | 
|  | if hasPrefix(name, "ffi_") { | 
|  | continue | 
|  | } | 
|  |  | 
|  | if foundFFICallback { | 
|  | break | 
|  | } | 
|  |  | 
|  | if name == "reflect.ffi_callback" { | 
|  | foundFFICallback = true | 
|  | continue | 
|  | } | 
|  |  | 
|  | // Ignore other functions in the reflect package. | 
|  | if hasPrefix(name, "reflect.") || hasPrefix(name, ".1reflect.") { | 
|  | continue | 
|  | } | 
|  |  | 
|  | // We should now be looking at the real caller. | 
|  | break | 
|  | } | 
|  |  | 
|  | if i < n { | 
|  | name = locs[i].function | 
|  | if hasPrefix(name, "runtime.") { | 
|  | return true | 
|  | } | 
|  | } | 
|  |  | 
|  | return false | 
|  | } | 
|  |  | 
|  | // This function is called when code is about to enter a function | 
|  | // created by the libffi version of reflect.MakeFunc. This function is | 
|  | // passed the names of the callers of the libffi code that called the | 
|  | // stub. It uses them to decide whether it is permitted to call | 
|  | // recover, and sets d.makefunccanrecover so that gorecover can make | 
|  | // the same decision. | 
|  | func makefuncfficanrecover(loc []location) { | 
|  | d := currentDefer() | 
|  | if d == nil { | 
|  | return | 
|  | } | 
|  |  | 
|  | // If we are already in a call stack of MakeFunc functions, | 
|  | // there is nothing we can usefully check here. | 
|  | if d.makefunccanrecover { | 
|  | return | 
|  | } | 
|  |  | 
|  | // loc starts with the caller of our caller. That will be a thunk. | 
|  | // If its caller was a function function, then it was called | 
|  | // directly by defer. | 
|  | if len(loc) < 2 { | 
|  | return | 
|  | } | 
|  |  | 
|  | name := loc[1].function | 
|  | if hasPrefix(name, "runtime.") { | 
|  | d.makefunccanrecover = true | 
|  | } | 
|  | } | 
|  |  | 
|  | // makefuncreturning is called when code is about to exit a function | 
|  | // created by reflect.MakeFunc. It is called by the function stub used | 
|  | // by reflect.MakeFunc. It clears the makefunccanrecover field. It's | 
|  | // OK to always clear this field, because canrecover will only be | 
|  | // called by a stub created for a function that calls recover. That | 
|  | // stub will not call a function created by reflect.MakeFunc, so by | 
|  | // the time we get here any caller higher up on the call stack no | 
|  | // longer needs the information. | 
|  | func makefuncreturning() { | 
|  | d := getg()._defer | 
|  | if d != nil { | 
|  | d.makefunccanrecover = false | 
|  | } | 
|  | } | 
|  |  | 
|  | // The implementation of the predeclared function recover. | 
|  | func gorecover() interface{} { | 
|  | gp := getg() | 
|  | p := gp._panic | 
|  | if p != nil && !p.recovered { | 
|  | p.recovered = true | 
|  | return p.arg | 
|  | } | 
|  | return nil | 
|  | } | 
|  |  | 
|  | // deferredrecover is called when a call to recover is deferred.  That | 
|  | // is, something like | 
|  | //   defer recover() | 
|  | // | 
|  | // We need to handle this specially.  In gc, the recover function | 
|  | // looks up the stack frame. In particular, that means that a deferred | 
|  | // recover will not recover a panic thrown in the same function that | 
|  | // defers the recover. It will only recover a panic thrown in a | 
|  | // function that defers the deferred call to recover. | 
|  | // | 
|  | // In other words: | 
|  | // | 
|  | // func f1() { | 
|  | // 	defer recover()	// does not stop panic | 
|  | // 	panic(0) | 
|  | // } | 
|  | // | 
|  | // func f2() { | 
|  | // 	defer func() { | 
|  | // 		defer recover()	// stops panic(0) | 
|  | // 	}() | 
|  | // 	panic(0) | 
|  | // } | 
|  | // | 
|  | // func f3() { | 
|  | // 	defer func() { | 
|  | // 		defer recover()	// does not stop panic | 
|  | // 		panic(0) | 
|  | // 	}() | 
|  | // 	panic(1) | 
|  | // } | 
|  | // | 
|  | // func f4() { | 
|  | // 	defer func() { | 
|  | // 		defer func() { | 
|  | // 			defer recover()	// stops panic(0) | 
|  | // 		}() | 
|  | // 		panic(0) | 
|  | // 	}() | 
|  | // 	panic(1) | 
|  | // } | 
|  | // | 
|  | // The interesting case here is f3. As can be seen from f2, the | 
|  | // deferred recover could pick up panic(1). However, this does not | 
|  | // happen because it is blocked by the panic(0). | 
|  | // | 
|  | // When a function calls recover, then when we invoke it we pass a | 
|  | // hidden parameter indicating whether it should recover something. | 
|  | // This parameter is set based on whether the function is being | 
|  | // invoked directly from defer. The parameter winds up determining | 
|  | // whether __go_recover or __go_deferred_recover is called at all. | 
|  | // | 
|  | // In the case of a deferred recover, the hidden parameter that | 
|  | // controls the call is actually the one set up for the function that | 
|  | // runs the defer recover() statement. That is the right thing in all | 
|  | // the cases above except for f3. In f3 the function is permitted to | 
|  | // call recover, but the deferred recover call is not. We address that | 
|  | // here by checking for that specific case before calling recover. If | 
|  | // this function was deferred when there is already a panic on the | 
|  | // panic stack, then we can only recover that panic, not any other. | 
|  |  | 
|  | // Note that we can get away with using a special function here | 
|  | // because you are not permitted to take the address of a predeclared | 
|  | // function like recover. | 
|  | func deferredrecover() interface{} { | 
|  | gp := getg() | 
|  | if gp._defer == nil || gp._defer.panicStack != gp._panic { | 
|  | return nil | 
|  | } | 
|  | return gorecover() | 
|  | } | 
|  |  | 
|  | //go:linkname sync_throw sync.throw | 
|  | func sync_throw(s string) { | 
|  | throw(s) | 
|  | } | 
|  |  | 
|  | //go:nosplit | 
|  | func throw(s string) { | 
|  | // Everything throw does should be recursively nosplit so it | 
|  | // can be called even when it's unsafe to grow the stack. | 
|  | systemstack(func() { | 
|  | print("fatal error: ", s, "\n") | 
|  | }) | 
|  | gp := getg() | 
|  | if gp.m.throwing == 0 { | 
|  | gp.m.throwing = 1 | 
|  | } | 
|  | fatalthrow() | 
|  | *(*int)(nil) = 0 // not reached | 
|  | } | 
|  |  | 
|  | // runningPanicDefers is non-zero while running deferred functions for panic. | 
|  | // runningPanicDefers is incremented and decremented atomically. | 
|  | // This is used to try hard to get a panic stack trace out when exiting. | 
|  | var runningPanicDefers uint32 | 
|  |  | 
|  | // panicking is non-zero when crashing the program for an unrecovered panic. | 
|  | // panicking is incremented and decremented atomically. | 
|  | var panicking uint32 | 
|  |  | 
|  | // paniclk is held while printing the panic information and stack trace, | 
|  | // so that two concurrent panics don't overlap their output. | 
|  | var paniclk mutex | 
|  |  | 
|  | // fatalthrow implements an unrecoverable runtime throw. It freezes the | 
|  | // system, prints stack traces starting from its caller, and terminates the | 
|  | // process. | 
|  | // | 
|  | //go:nosplit | 
|  | func fatalthrow() { | 
|  | pc := getcallerpc() | 
|  | sp := getcallersp() | 
|  | gp := getg() | 
|  |  | 
|  | startpanic_m() | 
|  |  | 
|  | if dopanic_m(gp, pc, sp) { | 
|  | crash() | 
|  | } | 
|  |  | 
|  | exit(2) | 
|  |  | 
|  | *(*int)(nil) = 0 // not reached | 
|  | } | 
|  |  | 
|  | // fatalpanic implements an unrecoverable panic. It is like fatalthrow, except | 
|  | // that if msgs != nil, fatalpanic also prints panic messages and decrements | 
|  | // runningPanicDefers once main is blocked from exiting. | 
|  | // | 
|  | //go:nosplit | 
|  | func fatalpanic(msgs *_panic) { | 
|  | pc := getcallerpc() | 
|  | sp := getcallersp() | 
|  | gp := getg() | 
|  | var docrash bool | 
|  |  | 
|  | if startpanic_m() && msgs != nil { | 
|  | // There were panic messages and startpanic_m | 
|  | // says it's okay to try to print them. | 
|  |  | 
|  | // startpanic_m set panicking, which will | 
|  | // block main from exiting, so now OK to | 
|  | // decrement runningPanicDefers. | 
|  | atomic.Xadd(&runningPanicDefers, -1) | 
|  |  | 
|  | printpanics(msgs) | 
|  | } | 
|  |  | 
|  | docrash = dopanic_m(gp, pc, sp) | 
|  |  | 
|  | if docrash { | 
|  | // By crashing outside the above systemstack call, debuggers | 
|  | // will not be confused when generating a backtrace. | 
|  | // Function crash is marked nosplit to avoid stack growth. | 
|  | crash() | 
|  | } | 
|  |  | 
|  | systemstack(func() { | 
|  | exit(2) | 
|  | }) | 
|  |  | 
|  | *(*int)(nil) = 0 // not reached | 
|  | } | 
|  |  | 
|  | // startpanic_m prepares for an unrecoverable panic. | 
|  | // | 
|  | // It returns true if panic messages should be printed, or false if | 
|  | // the runtime is in bad shape and should just print stacks. | 
|  | // | 
|  | // It must not have write barriers even though the write barrier | 
|  | // explicitly ignores writes once dying > 0. Write barriers still | 
|  | // assume that g.m.p != nil, and this function may not have P | 
|  | // in some contexts (e.g. a panic in a signal handler for a signal | 
|  | // sent to an M with no P). | 
|  | // | 
|  | //go:nowritebarrierrec | 
|  | func startpanic_m() bool { | 
|  | _g_ := getg() | 
|  | if mheap_.cachealloc.size == 0 { // very early | 
|  | print("runtime: panic before malloc heap initialized\n") | 
|  | } | 
|  | // Disallow malloc during an unrecoverable panic. A panic | 
|  | // could happen in a signal handler, or in a throw, or inside | 
|  | // malloc itself. We want to catch if an allocation ever does | 
|  | // happen (even if we're not in one of these situations). | 
|  | _g_.m.mallocing++ | 
|  |  | 
|  | // If we're dying because of a bad lock count, set it to a | 
|  | // good lock count so we don't recursively panic below. | 
|  | if _g_.m.locks < 0 { | 
|  | _g_.m.locks = 1 | 
|  | } | 
|  |  | 
|  | switch _g_.m.dying { | 
|  | case 0: | 
|  | // Setting dying >0 has the side-effect of disabling this G's writebuf. | 
|  | _g_.m.dying = 1 | 
|  | atomic.Xadd(&panicking, 1) | 
|  | lock(&paniclk) | 
|  | if debug.schedtrace > 0 || debug.scheddetail > 0 { | 
|  | schedtrace(true) | 
|  | } | 
|  | freezetheworld() | 
|  | return true | 
|  | case 1: | 
|  | // Something failed while panicking. | 
|  | // Just print a stack trace and exit. | 
|  | _g_.m.dying = 2 | 
|  | print("panic during panic\n") | 
|  | return false | 
|  | case 2: | 
|  | // This is a genuine bug in the runtime, we couldn't even | 
|  | // print the stack trace successfully. | 
|  | _g_.m.dying = 3 | 
|  | print("stack trace unavailable\n") | 
|  | exit(4) | 
|  | fallthrough | 
|  | default: | 
|  | // Can't even print! Just exit. | 
|  | exit(5) | 
|  | return false // Need to return something. | 
|  | } | 
|  | } | 
|  |  | 
|  | var didothers bool | 
|  | var deadlock mutex | 
|  |  | 
|  | func dopanic_m(gp *g, pc, sp uintptr) bool { | 
|  | if gp.sig != 0 { | 
|  | signame := signame(gp.sig) | 
|  | if signame != "" { | 
|  | print("[signal ", signame) | 
|  | } else { | 
|  | print("[signal ", hex(gp.sig)) | 
|  | } | 
|  | print(" code=", hex(gp.sigcode0), " addr=", hex(gp.sigcode1), " pc=", hex(gp.sigpc), "]\n") | 
|  | } | 
|  |  | 
|  | level, all, docrash := gotraceback() | 
|  | _g_ := getg() | 
|  | if level > 0 { | 
|  | if gp != gp.m.curg { | 
|  | all = true | 
|  | } | 
|  | if gp != gp.m.g0 { | 
|  | print("\n") | 
|  | goroutineheader(gp) | 
|  | traceback(0) | 
|  | } else if level >= 2 || _g_.m.throwing > 0 { | 
|  | print("\nruntime stack:\n") | 
|  | traceback(0) | 
|  | } | 
|  | if !didothers && all { | 
|  | didothers = true | 
|  | tracebackothers(gp) | 
|  | } | 
|  | } | 
|  | unlock(&paniclk) | 
|  |  | 
|  | if atomic.Xadd(&panicking, -1) != 0 { | 
|  | // Some other m is panicking too. | 
|  | // Let it print what it needs to print. | 
|  | // Wait forever without chewing up cpu. | 
|  | // It will exit when it's done. | 
|  | lock(&deadlock) | 
|  | lock(&deadlock) | 
|  | } | 
|  |  | 
|  | return docrash | 
|  | } | 
|  |  | 
|  | // canpanic returns false if a signal should throw instead of | 
|  | // panicking. | 
|  | // | 
|  | //go:nosplit | 
|  | func canpanic(gp *g) bool { | 
|  | // Note that g is m->gsignal, different from gp. | 
|  | // Note also that g->m can change at preemption, so m can go stale | 
|  | // if this function ever makes a function call. | 
|  | _g_ := getg() | 
|  | _m_ := _g_.m | 
|  |  | 
|  | // Is it okay for gp to panic instead of crashing the program? | 
|  | // Yes, as long as it is running Go code, not runtime code, | 
|  | // and not stuck in a system call. | 
|  | if gp == nil || gp != _m_.curg { | 
|  | return false | 
|  | } | 
|  | if _m_.locks != 0 || _m_.mallocing != 0 || _m_.throwing != 0 || _m_.preemptoff != "" || _m_.dying != 0 { | 
|  | return false | 
|  | } | 
|  | status := readgstatus(gp) | 
|  | if status&^_Gscan != _Grunning || gp.syscallsp != 0 { | 
|  | return false | 
|  | } | 
|  | return true | 
|  | } | 
|  |  | 
|  | // isAbortPC reports whether pc is the program counter at which | 
|  | // runtime.abort raises a signal. | 
|  | // | 
|  | // It is nosplit because it's part of the isgoexception | 
|  | // implementation. | 
|  | // | 
|  | //go:nosplit | 
|  | func isAbortPC(pc uintptr) bool { | 
|  | return false | 
|  | } |