aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/panic.go
diff options
context:
space:
mode:
authorMichael Anthony Knyszek <mknyszek@google.com>2018-12-18 20:04:53 +0000
committerMichael Knyszek <mknyszek@google.com>2018-12-19 00:13:22 +0000
commit9ed9df6ca27850704133de1ceb94407c635beb82 (patch)
tree73cad1a12511e6327963e0a69f1bbb952909f270 /src/runtime/panic.go
parente3b4b7baad555f74b6fbc0ddc00d46ed0ac03a0a (diff)
downloadgo-9ed9df6ca27850704133de1ceb94407c635beb82.tar.xz
runtime: avoid write barrier in startpanic_m
startpanic_m could be called correctly in a context where there's a valid G, a valid M, but no P, for example in a signal handler which panics. Currently, startpanic_m has write barriers enabled because write barriers are permitted if a G's M is dying. However, all the current write barrier implementations assume the current G has a P. Therefore, in this change we disable write barriers in startpanic_m, remove the only pointer write which clears g.writebuf, and fix up gwrite to ignore the writebuf if the current G's M is dying, rather than relying on it being nil in the dying case. Fixes #26575. Change-Id: I9b29e6b9edf00d8e99ffc71770c287142ebae086 Reviewed-on: https://go-review.googlesource.com/c/154837 Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com>
Diffstat (limited to 'src/runtime/panic.go')
-rw-r--r--src/runtime/panic.go11
1 files changed, 7 insertions, 4 deletions
diff --git a/src/runtime/panic.go b/src/runtime/panic.go
index 81ff21113f..bb83be4715 100644
--- a/src/runtime/panic.go
+++ b/src/runtime/panic.go
@@ -729,10 +729,13 @@ func fatalpanic(msgs *_panic) {
// It returns true if panic messages should be printed, or false if
// the runtime is in bad shape and should just print stacks.
//
-// It can have write barriers because the write barrier explicitly
-// ignores writes once dying > 0.
+// It must not have write barriers even though the write barrier
+// explicitly ignores writes once dying > 0. Write barriers still
+// assume that g.m.p != nil, and this function may not have P
+// in some contexts (e.g. a panic in a signal handler for a signal
+// sent to an M with no P).
//
-//go:yeswritebarrierrec
+//go:nowritebarrierrec
func startpanic_m() bool {
_g_ := getg()
if mheap_.cachealloc.size == 0 { // very early
@@ -752,8 +755,8 @@ func startpanic_m() bool {
switch _g_.m.dying {
case 0:
+ // Setting dying >0 has the side-effect of disabling this G's writebuf.
_g_.m.dying = 1
- _g_.writebuf = nil
atomic.Xadd(&panicking, 1)
lock(&paniclk)
if debug.schedtrace > 0 || debug.scheddetail > 0 {