mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: delay exiting while panic is running deferred functions
Try to avoid a race between the main goroutine exiting and a panic occurring. Don't try too hard, to avoid hanging. Updates #3934 Fixes #20018 Change-Id: I57a02b6d795d2a61f1cadd137ce097145280ece7 Reviewed-on: https://go-review.googlesource.com/41052 Reviewed-by: Austin Clements <austin@google.com>
This commit is contained in:
parent
3c745d750e
commit
2d86f49428
5 changed files with 87 additions and 4 deletions
|
|
@ -456,6 +456,8 @@ func gopanic(e interface{}) {
|
|||
p.link = gp._panic
|
||||
gp._panic = (*_panic)(noescape(unsafe.Pointer(&p)))
|
||||
|
||||
atomic.Xadd(&runningPanicDefers, 1)
|
||||
|
||||
for {
|
||||
d := gp._defer
|
||||
if d == nil {
|
||||
|
|
@ -504,6 +506,8 @@ func gopanic(e interface{}) {
|
|||
sp := unsafe.Pointer(d.sp) // must be pointer so it gets adjusted during stack copy
|
||||
freedefer(d)
|
||||
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.
|
||||
|
|
@ -527,6 +531,11 @@ func gopanic(e interface{}) {
|
|||
// and String methods to prepare the panic strings before startpanic.
|
||||
preprintpanics(gp._panic)
|
||||
startpanic()
|
||||
|
||||
// startpanic set panicking, which will block main from exiting,
|
||||
// so now OK to decrement runningPanicDefers.
|
||||
atomic.Xadd(&runningPanicDefers, -1)
|
||||
|
||||
printpanics(gp._panic)
|
||||
dopanic(0) // should not return
|
||||
*(*int)(nil) = 0 // not reached
|
||||
|
|
@ -597,7 +606,17 @@ func throw(s string) {
|
|||
*(*int)(nil) = 0 // not reached
|
||||
}
|
||||
|
||||
//uint32 runtime·panicking;
|
||||
// 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
|
||||
|
||||
// Unwind the stack after a deferred function calls recover
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue