]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: overwrite asyncPreempt PC when injecting sigpanic on Windows
authorCherry Zhang <cherryyz@google.com>
Wed, 8 Jan 2020 23:23:51 +0000 (18:23 -0500)
committerCherry Zhang <cherryyz@google.com>
Thu, 9 Jan 2020 15:37:52 +0000 (15:37 +0000)
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>
src/runtime/signal_windows.go

index 3b2c06b39c19d552610a7a4768983252b0363259..d123276d3efbb62954fff02fb2f3d5e1c3d2126c 100644 (file)
@@ -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))