aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/signal_windows.go
diff options
context:
space:
mode:
authorCherry Zhang <cherryyz@google.com>2020-01-08 18:23:51 -0500
committerCherry Zhang <cherryyz@google.com>2020-01-09 15:37:52 +0000
commit17e97322fb0605206d8503a321bd24eca17afd34 (patch)
treedcefbff8bb301897cba9a431684614c4afefa035 /src/runtime/signal_windows.go
parent817afe83578d869b36e8697344bb2d557c86b264 (diff)
downloadgo-17e97322fb0605206d8503a321bd24eca17afd34.tar.gz
go-17e97322fb0605206d8503a321bd24eca17afd34.zip
runtime: overwrite asyncPreempt PC when injecting sigpanic on Windows
On Windows, it might be possible that SuspendThread suspends a thread right between when an exception happens and when the exception handler runs. (This is my guess. I don't know the implementation detail of Windows exceptions to be sure.) In this case, we may inject a call to asyncPreempt before the exception handler runs. The exception handler will inject a sigpanic call, which will make the stack trace looks like sigpanic asyncPreempt actual panicking function i.e. it appears asyncPreempt panicked. Instead, just overwrite the PC, without pushing another frame. Fixes #35773. Change-Id: Ief4e964dcb7f45670b5f93c4dcf285cc1c737514 Reviewed-on: https://go-review.googlesource.com/c/go/+/213879 Run-TryBot: Cherry Zhang <cherryyz@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com>
Diffstat (limited to 'src/runtime/signal_windows.go')
-rw-r--r--src/runtime/signal_windows.go9
1 files changed, 8 insertions, 1 deletions
diff --git a/src/runtime/signal_windows.go b/src/runtime/signal_windows.go
index 3b2c06b39c..d123276d3e 100644
--- a/src/runtime/signal_windows.go
+++ b/src/runtime/signal_windows.go
@@ -129,7 +129,14 @@ func exceptionhandler(info *exceptionrecord, r *context, gp *g) int32 {
// make the trace look like a call to runtime·sigpanic instead.
// (Otherwise the trace will end at runtime·sigpanic and we
// won't get to see who faulted.)
- if r.ip() != 0 {
+ // Also don't push a sigpanic frame if the faulting PC
+ // is the entry of asyncPreempt. In this case, we suspended
+ // the thread right between the fault and the exception handler
+ // starting to run, and we have pushed an asyncPreempt call.
+ // The exception is not from asyncPreempt, so not to push a
+ // sigpanic call to make it look like that. Instead, just
+ // overwrite the PC. (See issue #35773)
+ if r.ip() != 0 && r.ip() != funcPC(asyncPreempt) {
sp := unsafe.Pointer(r.sp())
sp = add(sp, ^(unsafe.Sizeof(uintptr(0)) - 1)) // sp--
r.set_sp(uintptr(sp))