diff options
author | Cherry Zhang <cherryyz@google.com> | 2020-01-08 18:23:51 -0500 |
---|---|---|
committer | Cherry Zhang <cherryyz@google.com> | 2020-01-09 15:37:52 +0000 |
commit | 17e97322fb0605206d8503a321bd24eca17afd34 (patch) | |
tree | dcefbff8bb301897cba9a431684614c4afefa035 /src/runtime/signal_windows.go | |
parent | 817afe83578d869b36e8697344bb2d557c86b264 (diff) | |
download | go-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.go | 9 |
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)) |