108 lines
3.4 KiB
Diff
108 lines
3.4 KiB
Diff
|
|
From e83074ea52287115b85002a6b72137c72f6d7ecc Mon Sep 17 00:00:00 2001
|
||
|
|
From: Cherry Zhang <cherryyz@google.com>
|
||
|
|
Date: Sun, 10 Nov 2019 13:18:06 -0500
|
||
|
|
Subject: [PATCH 5/6] runtime: don't save G during VDSO if we're handling
|
||
|
|
signal
|
||
|
|
|
||
|
|
On some platforms (currently ARM and ARM64), when calling into
|
||
|
|
VDSO we store the G to the gsignal stack, if there is one, so if
|
||
|
|
we receive a signal during VDSO we can find the G.
|
||
|
|
|
||
|
|
If we receive a signal during VDSO, and within the signal handler
|
||
|
|
we call nanotime again (e.g. when handling profiling signal),
|
||
|
|
we'll save/clear the G slot on the gsignal stack again, which
|
||
|
|
clobbers the original saved G. If we receive a second signal
|
||
|
|
during the same VDSO execution, we will fetch a nil G, which will
|
||
|
|
lead to bad things such as deadlock.
|
||
|
|
|
||
|
|
Don't save G if we're calling VDSO code from the gsignal stack.
|
||
|
|
Saving G is not necessary as we won't receive a nested signal.
|
||
|
|
|
||
|
|
Fixes #35473.
|
||
|
|
|
||
|
|
Change-Id: Ibfd8587a3c70c2f1533908b056e81b94d75d65a5
|
||
|
|
Reviewed-on: https://go-review.googlesource.com/c/go/+/206397
|
||
|
|
Run-TryBot: Cherry Zhang <cherryyz@google.com>
|
||
|
|
TryBot-Result: Gobot Gobot <gobot@golang.org>
|
||
|
|
Reviewed-by: Bryan C. Mills <bcmills@google.com>
|
||
|
|
---
|
||
|
|
src/runtime/sys_linux_arm.s | 8 ++++++++
|
||
|
|
src/runtime/sys_linux_arm64.s | 8 ++++++++
|
||
|
|
2 files changed, 16 insertions(+)
|
||
|
|
|
||
|
|
diff --git a/src/runtime/sys_linux_arm.s b/src/runtime/sys_linux_arm.s
|
||
|
|
index a47ac5f..577faac 100644
|
||
|
|
--- a/src/runtime/sys_linux_arm.s
|
||
|
|
+++ b/src/runtime/sys_linux_arm.s
|
||
|
|
@@ -252,12 +252,16 @@ noswitch:
|
||
|
|
// so don't bother saving g.
|
||
|
|
// When using cgo, we already saved g on TLS, also don't save
|
||
|
|
// g here.
|
||
|
|
+ // Also don't save g if we are already on the signal stack.
|
||
|
|
+ // We won't get a nested signal.
|
||
|
|
MOVB runtime·iscgo(SB), R6
|
||
|
|
CMP $0, R6
|
||
|
|
BNE nosaveg
|
||
|
|
MOVW m_gsignal(R5), R6 // g.m.gsignal
|
||
|
|
CMP $0, R6
|
||
|
|
BEQ nosaveg
|
||
|
|
+ CMP g, R6
|
||
|
|
+ BEQ nosaveg
|
||
|
|
MOVW (g_stack+stack_lo)(R6), R6 // g.m.gsignal.stack.lo
|
||
|
|
MOVW g, (R6)
|
||
|
|
|
||
|
|
@@ -326,12 +330,16 @@ noswitch:
|
||
|
|
// so don't bother saving g.
|
||
|
|
// When using cgo, we already saved g on TLS, also don't save
|
||
|
|
// g here.
|
||
|
|
+ // Also don't save g if we are already on the signal stack.
|
||
|
|
+ // We won't get a nested signal.
|
||
|
|
MOVB runtime·iscgo(SB), R6
|
||
|
|
CMP $0, R6
|
||
|
|
BNE nosaveg
|
||
|
|
MOVW m_gsignal(R5), R6 // g.m.gsignal
|
||
|
|
CMP $0, R6
|
||
|
|
BEQ nosaveg
|
||
|
|
+ CMP g, R6
|
||
|
|
+ BEQ nosaveg
|
||
|
|
MOVW (g_stack+stack_lo)(R6), R6 // g.m.gsignal.stack.lo
|
||
|
|
MOVW g, (R6)
|
||
|
|
|
||
|
|
diff --git a/src/runtime/sys_linux_arm64.s b/src/runtime/sys_linux_arm64.s
|
||
|
|
index 94c93ca..a076744 100644
|
||
|
|
--- a/src/runtime/sys_linux_arm64.s
|
||
|
|
+++ b/src/runtime/sys_linux_arm64.s
|
||
|
|
@@ -214,10 +214,14 @@ noswitch:
|
||
|
|
// so don't bother saving g.
|
||
|
|
// When using cgo, we already saved g on TLS, also don't save
|
||
|
|
// g here.
|
||
|
|
+ // Also don't save g if we are already on the signal stack.
|
||
|
|
+ // We won't get a nested signal.
|
||
|
|
MOVBU runtime·iscgo(SB), R22
|
||
|
|
CBNZ R22, nosaveg
|
||
|
|
MOVD m_gsignal(R21), R22 // g.m.gsignal
|
||
|
|
CBZ R22, nosaveg
|
||
|
|
+ CMP g, R22
|
||
|
|
+ BEQ nosaveg
|
||
|
|
MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo
|
||
|
|
MOVD g, (R22)
|
||
|
|
|
||
|
|
@@ -278,10 +282,14 @@ noswitch:
|
||
|
|
// so don't bother saving g.
|
||
|
|
// When using cgo, we already saved g on TLS, also don't save
|
||
|
|
// g here.
|
||
|
|
+ // Also don't save g if we are already on the signal stack.
|
||
|
|
+ // We won't get a nested signal.
|
||
|
|
MOVBU runtime·iscgo(SB), R22
|
||
|
|
CBNZ R22, nosaveg
|
||
|
|
MOVD m_gsignal(R21), R22 // g.m.gsignal
|
||
|
|
CBZ R22, nosaveg
|
||
|
|
+ CMP g, R22
|
||
|
|
+ BEQ nosaveg
|
||
|
|
MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo
|
||
|
|
MOVD g, (R22)
|
||
|
|
|
||
|
|
--
|
||
|
|
2.17.1
|
||
|
|
|