mirror of
https://github.com/golang/go.git
synced 2025-05-05 23:53:05 +00:00
runtime: don't duplicate reraised panic values in printpanics
Change the output printed when crashing with a reraised panic value to not duplicate that value. Changes output of panicking with "PANIC", recovering, and reraising from: panic: PANIC [recovered] panic: PANIC to: panic: PANIC [recovered, reraised] Fixes #71517 Change-Id: Id59938c4ea0df555b851ffc650fe6f94c0845499 Reviewed-on: https://go-review.googlesource.com/c/go/+/645916 Reviewed-by: Michael Knyszek <mknyszek@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
9b4a462a7d
commit
478ad013f9
@ -1 +1,18 @@
|
|||||||
## Runtime {#runtime}
|
## Runtime {#runtime}
|
||||||
|
|
||||||
|
<!-- go.dev/issue/71517 -->
|
||||||
|
|
||||||
|
The message printed when a program exits due to an unhandled panic
|
||||||
|
that was recovered and re-raised no longer repeats the text of
|
||||||
|
the panic value.
|
||||||
|
|
||||||
|
Previously, a program which panicked with `panic("PANIC")`,
|
||||||
|
recovered the panic, and then re-panicked with the original
|
||||||
|
value would print:
|
||||||
|
|
||||||
|
panic: PANIC [recovered]
|
||||||
|
panic: PANIC
|
||||||
|
|
||||||
|
This program will now print:
|
||||||
|
|
||||||
|
panic: PANIC [recovered, reraised]
|
||||||
|
@ -356,6 +356,37 @@ panic: third panic
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReraisedPanic(t *testing.T) {
|
||||||
|
output := runTestProg(t, "testprog", "ReraisedPanic")
|
||||||
|
want := `panic: message [recovered, reraised]
|
||||||
|
`
|
||||||
|
if !strings.HasPrefix(output, want) {
|
||||||
|
t.Fatalf("output does not start with %q:\n%s", want, output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReraisedMiddlePanic(t *testing.T) {
|
||||||
|
output := runTestProg(t, "testprog", "ReraisedMiddlePanic")
|
||||||
|
want := `panic: inner [recovered]
|
||||||
|
panic: middle [recovered, reraised]
|
||||||
|
panic: outer
|
||||||
|
`
|
||||||
|
if !strings.HasPrefix(output, want) {
|
||||||
|
t.Fatalf("output does not start with %q:\n%s", want, output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReraisedPanicSandwich(t *testing.T) {
|
||||||
|
output := runTestProg(t, "testprog", "ReraisedPanicSandwich")
|
||||||
|
want := `panic: outer [recovered]
|
||||||
|
panic: inner [recovered]
|
||||||
|
panic: outer
|
||||||
|
`
|
||||||
|
if !strings.HasPrefix(output, want) {
|
||||||
|
t.Fatalf("output does not start with %q:\n%s", want, output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestGoexitCrash(t *testing.T) {
|
func TestGoexitCrash(t *testing.T) {
|
||||||
// External linking brings in cgo, causing deadlock detection not working.
|
// External linking brings in cgo, causing deadlock detection not working.
|
||||||
testenv.MustInternalLink(t, false)
|
testenv.MustInternalLink(t, false)
|
||||||
|
@ -649,6 +649,13 @@ func preprintpanics(p *_panic) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
for p != nil {
|
for p != nil {
|
||||||
|
if p.link != nil && *efaceOf(&p.link.arg) == *efaceOf(&p.arg) {
|
||||||
|
// This panic contains the same value as the next one in the chain.
|
||||||
|
// Mark it as reraised. We will skip printing it twice in a row.
|
||||||
|
p.link.reraised = true
|
||||||
|
p = p.link
|
||||||
|
continue
|
||||||
|
}
|
||||||
switch v := p.arg.(type) {
|
switch v := p.arg.(type) {
|
||||||
case error:
|
case error:
|
||||||
p.arg = v.Error()
|
p.arg = v.Error()
|
||||||
@ -664,6 +671,9 @@ func preprintpanics(p *_panic) {
|
|||||||
func printpanics(p *_panic) {
|
func printpanics(p *_panic) {
|
||||||
if p.link != nil {
|
if p.link != nil {
|
||||||
printpanics(p.link)
|
printpanics(p.link)
|
||||||
|
if p.link.reraised {
|
||||||
|
return
|
||||||
|
}
|
||||||
if !p.link.goexit {
|
if !p.link.goexit {
|
||||||
print("\t")
|
print("\t")
|
||||||
}
|
}
|
||||||
@ -673,7 +683,9 @@ func printpanics(p *_panic) {
|
|||||||
}
|
}
|
||||||
print("panic: ")
|
print("panic: ")
|
||||||
printpanicval(p.arg)
|
printpanicval(p.arg)
|
||||||
if p.recovered {
|
if p.reraised {
|
||||||
|
print(" [recovered, reraised]")
|
||||||
|
} else if p.recovered {
|
||||||
print(" [recovered]")
|
print(" [recovered]")
|
||||||
}
|
}
|
||||||
print("\n")
|
print("\n")
|
||||||
|
@ -1016,6 +1016,7 @@ type _panic struct {
|
|||||||
slotsPtr unsafe.Pointer
|
slotsPtr unsafe.Pointer
|
||||||
|
|
||||||
recovered bool // whether this panic has been recovered
|
recovered bool // whether this panic has been recovered
|
||||||
|
reraised bool // whether this panic was reraised
|
||||||
goexit bool
|
goexit bool
|
||||||
deferreturn bool
|
deferreturn bool
|
||||||
}
|
}
|
||||||
|
52
src/runtime/testdata/testprog/crash.go
vendored
52
src/runtime/testdata/testprog/crash.go
vendored
@ -19,6 +19,9 @@ func init() {
|
|||||||
register("StringPanic", StringPanic)
|
register("StringPanic", StringPanic)
|
||||||
register("NilPanic", NilPanic)
|
register("NilPanic", NilPanic)
|
||||||
register("CircularPanic", CircularPanic)
|
register("CircularPanic", CircularPanic)
|
||||||
|
register("ReraisedPanic", ReraisedPanic)
|
||||||
|
register("ReraisedMiddlePanic", ReraisedMiddlePanic)
|
||||||
|
register("ReraisedPanicSandwich", ReraisedPanicSandwich)
|
||||||
}
|
}
|
||||||
|
|
||||||
func test(name string) {
|
func test(name string) {
|
||||||
@ -137,3 +140,52 @@ func (e exampleCircleEndError) Error() string {
|
|||||||
func CircularPanic() {
|
func CircularPanic() {
|
||||||
panic(exampleCircleStartError{})
|
panic(exampleCircleStartError{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ReraisedPanic() {
|
||||||
|
defer func() {
|
||||||
|
panic(recover())
|
||||||
|
}()
|
||||||
|
panic("message")
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReraisedMiddlePanic() {
|
||||||
|
defer func() {
|
||||||
|
recover()
|
||||||
|
panic("outer")
|
||||||
|
}()
|
||||||
|
func() {
|
||||||
|
defer func() {
|
||||||
|
panic(recover())
|
||||||
|
}()
|
||||||
|
func() {
|
||||||
|
defer func() {
|
||||||
|
recover()
|
||||||
|
panic("middle")
|
||||||
|
}()
|
||||||
|
panic("inner")
|
||||||
|
}()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Panic sandwich:
|
||||||
|
//
|
||||||
|
// panic("outer") =>
|
||||||
|
// recovered, panic("inner") =>
|
||||||
|
// panic(recovered outer panic value)
|
||||||
|
//
|
||||||
|
// Exercises the edge case where we reraise a panic value,
|
||||||
|
// but with another panic in the middle.
|
||||||
|
func ReraisedPanicSandwich() {
|
||||||
|
var outer any
|
||||||
|
defer func() {
|
||||||
|
recover()
|
||||||
|
panic(outer)
|
||||||
|
}()
|
||||||
|
func() {
|
||||||
|
defer func() {
|
||||||
|
outer = recover()
|
||||||
|
panic("inner")
|
||||||
|
}()
|
||||||
|
panic("outer")
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user