]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: use innermost frame's func name for async preemption check
authorCherry Zhang <cherryyz@google.com>
Wed, 18 Dec 2019 20:19:05 +0000 (15:19 -0500)
committerCherry Zhang <cherryyz@google.com>
Wed, 18 Dec 2019 21:02:58 +0000 (21:02 +0000)
We don't asynchronously preempt if we are in the runtime. We do
this by checking the function name. However, it failed to take
inlining into account. If a runtime function gets inlined into
a non-runtime function, it can be preempted, and bad things can
happen. One instance of this is dounlockOSThread inlined into
UnlockOSThread which is in turn inlined into a non-runtime
function.

Fix this by using the innermost frame's function name.

Change-Id: Ifa036ce1320700aaaefd829b4bee0d04d05c395d
Reviewed-on: https://go-review.googlesource.com/c/go/+/211978
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
src/runtime/preempt.go

index 2c38ac02f51304d6e8637a9c5c782a416d07f533..420a7f96e089fae0a711f1ed52711ac3a84c17aa 100644 (file)
@@ -411,9 +411,17 @@ func isAsyncSafePoint(gp *g, pc, sp, lr uintptr) bool {
                // locals pointer map, like empty frame functions?
                return false
        }
-       if hasPrefix(funcname(f), "runtime.") ||
-               hasPrefix(funcname(f), "runtime/internal/") ||
-               hasPrefix(funcname(f), "reflect.") {
+       name := funcname(f)
+       if inldata := funcdata(f, _FUNCDATA_InlTree); inldata != nil {
+               inltree := (*[1 << 20]inlinedCall)(inldata)
+               ix := pcdatavalue(f, _PCDATA_InlTreeIndex, pc, nil)
+               if ix >= 0 {
+                       name = funcnameFromNameoff(f, inltree[ix].func_)
+               }
+       }
+       if hasPrefix(name, "runtime.") ||
+               hasPrefix(name, "runtime/internal/") ||
+               hasPrefix(name, "reflect.") {
                // For now we never async preempt the runtime or
                // anything closely tied to the runtime. Known issues
                // include: various points in the scheduler ("don't