aboutsummaryrefslogtreecommitdiff
path: root/libgo/go
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2019-02-19 15:32:34 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2019-02-19 15:32:34 +0000
commit6bd37418a378bec4916ad70403375af00df91938 (patch)
tree6cc264135130829edd8bf0fa234f727d4f929cc6 /libgo/go
parent23c4471ee530a7a752ca8c7eff111aaa39e8d118 (diff)
downloadgcc-6bd37418a378bec4916ad70403375af00df91938.zip
gcc-6bd37418a378bec4916ad70403375af00df91938.tar.gz
gcc-6bd37418a378bec4916ad70403375af00df91938.tar.bz2
runtime: abort stack scan in cases that we cannot unwind the stack
In signal-triggered stack scan, if the signal is delivered at certain bad time (e.g. in vdso, or in the middle of setcontext?), the unwinder may not be able to unwind the whole stack, while it still reports _URC_END_OF_STACK. So we cannot rely on _URC_END_OF_STACK to tell if it successfully scanned the stack. Instead, we check the last Go frame to see it actually reached the end of the stack. For Go-created stack, this is runtime.kickoff. For C-created stack, we need to record the outermost Go frame when it enters the Go side. Also we cannot unwind the stack if the signal is delivered in the middle of runtime.gogo, halfway through a goroutine switch, where the g and the stack don't match. Give up in this case as well. Reviewed-on: https://go-review.googlesource.com/c/159098 From-SVN: r269018
Diffstat (limited to 'libgo/go')
-rw-r--r--libgo/go/runtime/cgo_gccgo.go4
-rw-r--r--libgo/go/runtime/proc.go3
-rw-r--r--libgo/go/runtime/runtime2.go1
-rw-r--r--libgo/go/runtime/stubs.go4
4 files changed, 12 insertions, 0 deletions
diff --git a/libgo/go/runtime/cgo_gccgo.go b/libgo/go/runtime/cgo_gccgo.go
index aff8130..e4d27e8 100644
--- a/libgo/go/runtime/cgo_gccgo.go
+++ b/libgo/go/runtime/cgo_gccgo.go
@@ -80,6 +80,10 @@ func CgocallBack() {
gp = getg()
mp := gp.m
mp.dropextram = true
+
+ // This is a C-created stack.
+ // Record the outermost Go frame to help stack scan.
+ gp.entrysp = getcallersp()
}
lockOSThread()
diff --git a/libgo/go/runtime/proc.go b/libgo/go/runtime/proc.go
index e937563..1c944d6 100644
--- a/libgo/go/runtime/proc.go
+++ b/libgo/go/runtime/proc.go
@@ -1192,6 +1192,9 @@ func kickoff() {
gp.param = nil
}
+ // Record the entry SP to help stack scan.
+ gp.entrysp = getsp()
+
fv(param)
goexit1()
}
diff --git a/libgo/go/runtime/runtime2.go b/libgo/go/runtime/runtime2.go
index 4cd68da..4f823e0 100644
--- a/libgo/go/runtime/runtime2.go
+++ b/libgo/go/runtime/runtime2.go
@@ -433,6 +433,7 @@ type g struct {
entry func(unsafe.Pointer) // goroutine function to run
entryfn uintptr // function address passed to __go_go
+ entrysp uintptr // the stack pointer of the outermost Go frame
fromgogo bool // whether entered from gogo function
scanningself bool // whether goroutine is scanning its own stack
diff --git a/libgo/go/runtime/stubs.go b/libgo/go/runtime/stubs.go
index 9f5191b..dfdb38e 100644
--- a/libgo/go/runtime/stubs.go
+++ b/libgo/go/runtime/stubs.go
@@ -231,6 +231,10 @@ func getcallerpc() uintptr
//go:noescape
func getcallersp() uintptr // implemented as an intrinsic on all platforms
+// getsp returns the stack pointer (SP) of the caller of getsp.
+//go:noinline
+func getsp() uintptr { return getcallersp() }
+
func asmcgocall(fn, arg unsafe.Pointer) int32 {
throw("asmcgocall")
return 0