From 17e97322fb0605206d8503a321bd24eca17afd34 Mon Sep 17 00:00:00 2001 From: Cherry Zhang Date: Wed, 8 Jan 2020 18:23:51 -0500 Subject: [PATCH] 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 --- src/runtime/signal_windows.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) 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)) -- 2.50.0