diff options
| author | Michael Anthony Knyszek <mknyszek@google.com> | 2018-12-18 20:04:53 +0000 |
|---|---|---|
| committer | Michael Knyszek <mknyszek@google.com> | 2018-12-19 00:13:22 +0000 |
| commit | 9ed9df6ca27850704133de1ceb94407c635beb82 (patch) | |
| tree | 73cad1a12511e6327963e0a69f1bbb952909f270 /src/runtime/panic.go | |
| parent | e3b4b7baad555f74b6fbc0ddc00d46ed0ac03a0a (diff) | |
| download | go-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.go | 11 |
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 { |
