From: Cherry Zhang Date: Wed, 8 Jan 2020 23:23:51 +0000 (-0500) Subject: runtime: overwrite asyncPreempt PC when injecting sigpanic on Windows X-Git-Tag: go1.14rc1~142 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=17e97322fb0605206d8503a321bd24eca17afd34;p=gostls13.git 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 TryBot-Result: Gobot Gobot Reviewed-by: Austin Clements --- 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))