mirror of
https://github.com/golang/go
synced 2024-11-19 12:14:42 -07:00
runtime: never allocate during an unrecoverable panic
Currently, startpanic_m (which prepares for an unrecoverable panic) goes out of its way to make it possible to allocate during panic handling by allocating an mcache if there isn't one. However, this is both potentially dangerous and unnecessary. Allocating an mcache is a generally complex thing to do in an already precarious situation. Specifically, it requires obtaining the heap lock, and there's evidence that this may be able to deadlock (#23360). However, it's also unnecessary because we never allocate from the unrecoverable panic path. This didn't use to be the case. The call to allocmcache was introduced long ago, in CL 7388043, where it was in preparation for separating Ms and Ps and potentially running an M without an mcache. At the time, after calling startpanic, the runtime could call String and Error methods on panicked values, which could do anything including allocating. That was generally unsafe even at the time, and CL 19792 fixed this be pre-printing panic messages before calling startpanic. As a result, we now no longer allocate after calling startpanic. This CL not only removes the allocmcache call, but goes a step further to explicitly disallow any allocation during unrecoverable panic handling, even in situations where it might be safe. This way, if panic handling ever does an allocation that would be unsafe in unusual circumstances, we'll know even if it happens during normal circumstances. This would help with debugging #23360, since the deadlock in allocmcache is currently masking the real failure. Beyond all.bash, I manually tested this change by adding panics at various points in early runtime init, signal handling, and the scheduler to check unusual panic situations. Change-Id: I85df21e2b4b20c6faf1f13fae266c9339eebc061 Reviewed-on: https://go-review.googlesource.com/88835 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
9483a0bc23
commit
2edc4d4634
@ -72,8 +72,7 @@ func typestring(x interface{}) string {
|
||||
return e._type.string()
|
||||
}
|
||||
|
||||
// For calling from C.
|
||||
// Prints an argument passed to panic.
|
||||
// printany prints an argument passed to panic.
|
||||
func printany(i interface{}) {
|
||||
switch v := i.(type) {
|
||||
case nil:
|
||||
|
@ -408,12 +408,15 @@ func preprintpanics(p *_panic) {
|
||||
}
|
||||
|
||||
// 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: ")
|
||||
// Because of preprintpanics, p.arg cannot be an error or
|
||||
// stringer, so this won't call into user code.
|
||||
printany(p.arg)
|
||||
if p.recovered {
|
||||
print(" [recovered]")
|
||||
@ -654,7 +657,7 @@ func recovery(gp *g) {
|
||||
gogo(&gp.sched)
|
||||
}
|
||||
|
||||
// startpanic_m implements unrecoverable panic.
|
||||
// startpanic_m prepares for an unrecoverable panic.
|
||||
//
|
||||
// It can have write barriers because the write barrier explicitly
|
||||
// ignores writes once dying > 0.
|
||||
@ -664,10 +667,12 @@ 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()
|
||||
}
|
||||
// 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++
|
||||
|
||||
switch _g_.m.dying {
|
||||
case 0:
|
||||
|
Loading…
Reference in New Issue
Block a user