mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: merge panic1.go into panic.go
A TODO to merge is removed from panic1.go. The rest is appended to panic.go Updates #12952 Change-Id: Ied4382a455abc20bc2938e34d031802e6b4baf8b Reviewed-on: https://go-review.googlesource.com/15905 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
d72d299f3e
commit
9358f7fa61
2 changed files with 142 additions and 150 deletions
|
|
@ -527,3 +527,145 @@ func throw(s string) {
|
||||||
dopanic(0)
|
dopanic(0)
|
||||||
*(*int)(nil) = 0 // not reached
|
*(*int)(nil) = 0 // not reached
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//uint32 runtime·panicking;
|
||||||
|
var paniclk mutex
|
||||||
|
|
||||||
|
const hasLinkRegister = GOARCH == "arm" || GOARCH == "arm64" || GOARCH == "ppc64" || GOARCH == "ppc64le"
|
||||||
|
|
||||||
|
// Unwind the stack after a deferred function calls recover
|
||||||
|
// after a panic. Then arrange to continue running as though
|
||||||
|
// the caller of the deferred function returned normally.
|
||||||
|
func recovery(gp *g) {
|
||||||
|
// Info about defer passed in G struct.
|
||||||
|
sp := gp.sigcode0
|
||||||
|
pc := gp.sigcode1
|
||||||
|
|
||||||
|
// d's arguments need to be in the stack.
|
||||||
|
if sp != 0 && (sp < gp.stack.lo || gp.stack.hi < sp) {
|
||||||
|
print("recover: ", hex(sp), " not in [", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n")
|
||||||
|
throw("bad recovery")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make the deferproc for this d return again,
|
||||||
|
// this time returning 1. The calling function will
|
||||||
|
// jump to the standard return epilogue.
|
||||||
|
gcUnwindBarriers(gp, sp)
|
||||||
|
gp.sched.sp = sp
|
||||||
|
gp.sched.pc = pc
|
||||||
|
gp.sched.lr = 0
|
||||||
|
gp.sched.ret = 1
|
||||||
|
gogo(&gp.sched)
|
||||||
|
}
|
||||||
|
|
||||||
|
func startpanic_m() {
|
||||||
|
_g_ := getg()
|
||||||
|
if mheap_.cachealloc.size == 0 { // very early
|
||||||
|
print("runtime: panic before malloc heap initialized\n")
|
||||||
|
_g_.m.mallocing = 1 // tell rest of panic not to try to malloc
|
||||||
|
} else if _g_.m.mcache == nil { // can happen if called from signal handler or throw
|
||||||
|
_g_.m.mcache = allocmcache()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch _g_.m.dying {
|
||||||
|
case 0:
|
||||||
|
_g_.m.dying = 1
|
||||||
|
if _g_ != nil {
|
||||||
|
_g_.writebuf = nil
|
||||||
|
}
|
||||||
|
xadd(&panicking, 1)
|
||||||
|
lock(&paniclk)
|
||||||
|
if debug.schedtrace > 0 || debug.scheddetail > 0 {
|
||||||
|
schedtrace(true)
|
||||||
|
}
|
||||||
|
freezetheworld()
|
||||||
|
return
|
||||||
|
case 1:
|
||||||
|
// Something failed while panicing, probably the print of the
|
||||||
|
// argument to panic(). Just print a stack trace and exit.
|
||||||
|
_g_.m.dying = 2
|
||||||
|
print("panic during panic\n")
|
||||||
|
dopanic(0)
|
||||||
|
exit(3)
|
||||||
|
fallthrough
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var didothers bool
|
||||||
|
var deadlock mutex
|
||||||
|
|
||||||
|
func dopanic_m(gp *g, pc, sp uintptr) {
|
||||||
|
if gp.sig != 0 {
|
||||||
|
print("[signal ", hex(gp.sig), " code=", hex(gp.sigcode0), " addr=", hex(gp.sigcode1), " pc=", hex(gp.sigpc), "]\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
var docrash bool
|
||||||
|
_g_ := getg()
|
||||||
|
if t := gotraceback(&docrash); t > 0 {
|
||||||
|
if gp != gp.m.g0 {
|
||||||
|
print("\n")
|
||||||
|
goroutineheader(gp)
|
||||||
|
traceback(pc, sp, 0, gp)
|
||||||
|
} else if t >= 2 || _g_.m.throwing > 0 {
|
||||||
|
print("\nruntime stack:\n")
|
||||||
|
traceback(pc, sp, 0, gp)
|
||||||
|
}
|
||||||
|
if !didothers {
|
||||||
|
didothers = true
|
||||||
|
tracebackothers(gp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unlock(&paniclk)
|
||||||
|
|
||||||
|
if 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
if docrash {
|
||||||
|
crash()
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
//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-_m_.softfloat != 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
|
||||||
|
}
|
||||||
|
if GOOS == "windows" && _m_.libcallsp != 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,150 +0,0 @@
|
||||||
// Copyright 2012 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
|
|
||||||
|
|
||||||
// Code related to defer, panic and recover.
|
|
||||||
// TODO: Merge into panic.go.
|
|
||||||
|
|
||||||
//uint32 runtime·panicking;
|
|
||||||
var paniclk mutex
|
|
||||||
|
|
||||||
const hasLinkRegister = GOARCH == "arm" || GOARCH == "arm64" || GOARCH == "ppc64" || GOARCH == "ppc64le"
|
|
||||||
|
|
||||||
// Unwind the stack after a deferred function calls recover
|
|
||||||
// after a panic. Then arrange to continue running as though
|
|
||||||
// the caller of the deferred function returned normally.
|
|
||||||
func recovery(gp *g) {
|
|
||||||
// Info about defer passed in G struct.
|
|
||||||
sp := gp.sigcode0
|
|
||||||
pc := gp.sigcode1
|
|
||||||
|
|
||||||
// d's arguments need to be in the stack.
|
|
||||||
if sp != 0 && (sp < gp.stack.lo || gp.stack.hi < sp) {
|
|
||||||
print("recover: ", hex(sp), " not in [", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n")
|
|
||||||
throw("bad recovery")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make the deferproc for this d return again,
|
|
||||||
// this time returning 1. The calling function will
|
|
||||||
// jump to the standard return epilogue.
|
|
||||||
gcUnwindBarriers(gp, sp)
|
|
||||||
gp.sched.sp = sp
|
|
||||||
gp.sched.pc = pc
|
|
||||||
gp.sched.lr = 0
|
|
||||||
gp.sched.ret = 1
|
|
||||||
gogo(&gp.sched)
|
|
||||||
}
|
|
||||||
|
|
||||||
func startpanic_m() {
|
|
||||||
_g_ := getg()
|
|
||||||
if mheap_.cachealloc.size == 0 { // very early
|
|
||||||
print("runtime: panic before malloc heap initialized\n")
|
|
||||||
_g_.m.mallocing = 1 // tell rest of panic not to try to malloc
|
|
||||||
} else if _g_.m.mcache == nil { // can happen if called from signal handler or throw
|
|
||||||
_g_.m.mcache = allocmcache()
|
|
||||||
}
|
|
||||||
|
|
||||||
switch _g_.m.dying {
|
|
||||||
case 0:
|
|
||||||
_g_.m.dying = 1
|
|
||||||
if _g_ != nil {
|
|
||||||
_g_.writebuf = nil
|
|
||||||
}
|
|
||||||
xadd(&panicking, 1)
|
|
||||||
lock(&paniclk)
|
|
||||||
if debug.schedtrace > 0 || debug.scheddetail > 0 {
|
|
||||||
schedtrace(true)
|
|
||||||
}
|
|
||||||
freezetheworld()
|
|
||||||
return
|
|
||||||
case 1:
|
|
||||||
// Something failed while panicing, probably the print of the
|
|
||||||
// argument to panic(). Just print a stack trace and exit.
|
|
||||||
_g_.m.dying = 2
|
|
||||||
print("panic during panic\n")
|
|
||||||
dopanic(0)
|
|
||||||
exit(3)
|
|
||||||
fallthrough
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var didothers bool
|
|
||||||
var deadlock mutex
|
|
||||||
|
|
||||||
func dopanic_m(gp *g, pc, sp uintptr) {
|
|
||||||
if gp.sig != 0 {
|
|
||||||
print("[signal ", hex(gp.sig), " code=", hex(gp.sigcode0), " addr=", hex(gp.sigcode1), " pc=", hex(gp.sigpc), "]\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
var docrash bool
|
|
||||||
_g_ := getg()
|
|
||||||
if t := gotraceback(&docrash); t > 0 {
|
|
||||||
if gp != gp.m.g0 {
|
|
||||||
print("\n")
|
|
||||||
goroutineheader(gp)
|
|
||||||
traceback(pc, sp, 0, gp)
|
|
||||||
} else if t >= 2 || _g_.m.throwing > 0 {
|
|
||||||
print("\nruntime stack:\n")
|
|
||||||
traceback(pc, sp, 0, gp)
|
|
||||||
}
|
|
||||||
if !didothers {
|
|
||||||
didothers = true
|
|
||||||
tracebackothers(gp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
unlock(&paniclk)
|
|
||||||
|
|
||||||
if 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
if docrash {
|
|
||||||
crash()
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(2)
|
|
||||||
}
|
|
||||||
|
|
||||||
//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-_m_.softfloat != 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
|
|
||||||
}
|
|
||||||
if GOOS == "windows" && _m_.libcallsp != 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue