]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: include pre-panic/throw logs in core dumps
authorRhys Hiltner <rhys@justin.tv>
Tue, 25 Oct 2016 18:56:29 +0000 (11:56 -0700)
committerRuss Cox <rsc@golang.org>
Fri, 11 Nov 2016 21:29:53 +0000 (21:29 +0000)
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: Russ Cox <rsc@golang.org>
src/runtime/print.go

index 5f8233524463da706547319c878b84cee926bc4f..8fa3d3990526ada65d96e8ccf27a89f30c696f87 100644 (file)
@@ -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)