Commit e0aedfb4 authored by Rhys Hiltner's avatar Rhys Hiltner Committed by Russ Cox

runtime: include pre-panic/throw logs in core dumps

When a Go program crashes with GOTRACEBACK=crash, the OS creates a
core dump. Include the text-formatted output of some of the cause of
that crash in the core dump.

Output printed by the runtime before crashing is maintained in a
circular buffer to allow access to messages that may be printed
immediately before calling runtime.throw.

The stack traces printed by the runtime as it crashes are not stored.
The information required to recreate them should be included in the
core file.

Updates #16893

There are no tests covering the generation of core dumps; this change
has not added any.

This adds (reentrant) locking to runtime.gwrite, which may have an
undesired performance impact.

Change-Id: Ia2463be3c12429354d290bdec5f3c8d565d1a2c3
Reviewed-on: https://go-review.googlesource.com/32013
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
parent 10d2efd0
......@@ -4,7 +4,10 @@
package runtime
import "unsafe"
import (
"runtime/internal/atomic"
"unsafe"
)
// The compiler knows that a print of a value of this type
// should use printhex instead of printuint (decimal).
......@@ -19,6 +22,36 @@ func bytes(s string) (ret []byte) {
return
}
var (
// printBacklog is a circular buffer of messages written with the builtin
// print* functions, for use in postmortem analysis of core dumps.
printBacklog [512]byte
printBacklogIndex int
)
// recordForPanic maintains a circular buffer of messages written by the
// runtime leading up to a process crash, allowing the messages to be
// extracted from a core dump.
//
// The text written during a process crash (following "panic" or "fatal
// error") is not saved, since the goroutine stacks will generally be readable
// from the runtime datastructures in the core file.
func recordForPanic(b []byte) {
printlock()
if atomic.Load(&panicking) == 0 {
// Not actively crashing: maintain circular buffer of print output.
for i := 0; i < len(b); {
n := copy(printBacklog[printBacklogIndex:], b[i:])
i += n
printBacklogIndex += n
printBacklogIndex %= len(printBacklog)
}
}
printunlock()
}
var debuglock mutex
// The compiler emits calls to printlock and printunlock around
......@@ -53,6 +86,7 @@ func gwrite(b []byte) {
if len(b) == 0 {
return
}
recordForPanic(b)
gp := getg()
if gp == nil || gp.writebuf == nil {
writeErr(b)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment