]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: don't fetch G from signal stack when using cgo
authorCherry Zhang <cherryyz@google.com>
Thu, 31 Oct 2019 14:32:31 +0000 (10:32 -0400)
committerCherry Zhang <cherryyz@google.com>
Tue, 5 Nov 2019 18:58:41 +0000 (18:58 +0000)
When using cgo, we save G to TLS, and when a signal happens, we
load G from TLS in sigtramp. This should give us a valid G. Don't
try to fetch from the signal stack. In particular, C code may
change the signal stack or call our signal handler directly (e.g.
TSAN), so we are not necessarily running on the original gsignal
stack where we saved G.

Also skip saving G on the signal stack when using cgo.

Updates #35249.

Change-Id: I40749ce6682709bd4ebfdfd9f23bd0f317fc197d
Reviewed-on: https://go-review.googlesource.com/c/go/+/204519
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/runtime/signal_unix.go
src/runtime/sys_linux_arm.s
src/runtime/sys_linux_arm64.s

index 6563186392ce4c96e7539dd0cddc2dbdc93ba85d..fab8574d1c10ec8acd5f3477a936533724f235ee 100644 (file)
@@ -360,9 +360,11 @@ func preemptM(mp *m) {
 func sigFetchG(c *sigctxt) *g {
        switch GOARCH {
        case "arm", "arm64":
-               if inVDSOPage(c.sigpc()) {
-                       // Before making a VDSO call we save the g to the bottom of the
-                       // signal stack. Fetch from there.
+               if !iscgo && inVDSOPage(c.sigpc()) {
+                       // When using cgo, we save the g on TLS and load it from there
+                       // in sigtramp. Just use that.
+                       // Otherwise, before making a VDSO call we save the g to the
+                       // bottom of the signal stack. Fetch from there.
                        // TODO: in efence mode, stack is sysAlloc'd, so this wouldn't
                        // work.
                        sp := getcallersp()
index 9ef8c9258b8949b53581c34bf61216c66370bc15..b8dc202d4c9dac1ac41a6dbd84692e04be60557e 100644 (file)
@@ -277,21 +277,28 @@ noswitch:
        // during VDSO code we can find the g.
        // If we don't have a signal stack, we won't receive signal,
        // so don't bother saving g.
+       // When using cgo, we already saved g on TLS, also don't save
+       // g here.
+       MOVB    runtime·iscgo(SB), R6
+       CMP     $0, R6
+       BNE     nosaveg
        MOVW    m_gsignal(R5), R6          // g.m.gsignal
        CMP     $0, R6
-       BEQ     3(PC)
+       BEQ     nosaveg
        MOVW    (g_stack+stack_lo)(R6), R6 // g.m.gsignal.stack.lo
        MOVW    g, (R6)
 
        BL      (R11)
 
-       CMP     $0, R6   // R6 is unchanged by C code
-       BEQ     3(PC)
        MOVW    $0, R1
-       MOVW    R1, (R6) // clear g slot
+       MOVW    R1, (R6) // clear g slot, R6 is unchanged by C code
 
        JMP     finish
 
+nosaveg:
+       BL      (R11)
+       JMP     finish
+
 fallback:
        MOVW    $SYS_clock_gettime, R7
        SWI     $0
@@ -344,21 +351,28 @@ noswitch:
        // during VDSO code we can find the g.
        // If we don't have a signal stack, we won't receive signal,
        // so don't bother saving g.
+       // When using cgo, we already saved g on TLS, also don't save
+       // g here.
+       MOVB    runtime·iscgo(SB), R6
+       CMP     $0, R6
+       BNE     nosaveg
        MOVW    m_gsignal(R5), R6          // g.m.gsignal
        CMP     $0, R6
-       BEQ     3(PC)
+       BEQ     nosaveg
        MOVW    (g_stack+stack_lo)(R6), R6 // g.m.gsignal.stack.lo
        MOVW    g, (R6)
 
        BL      (R11)
 
-       CMP     $0, R6   // R6 is unchanged by C code
-       BEQ     3(PC)
        MOVW    $0, R1
-       MOVW    R1, (R6) // clear g slot
+       MOVW    R1, (R6) // clear g slot, R6 is unchanged by C code
 
        JMP     finish
 
+nosaveg:
+       BL      (R11)
+       JMP     finish
+
 fallback:
        MOVW    $SYS_clock_gettime, R7
        SWI     $0
index e0d681ebf1269513a3a902532edaef132a3ab106..ddfb13d7a1816178a6ebcfa70a1f7dc2c2e95b6f 100644 (file)
@@ -237,18 +237,25 @@ noswitch:
        // during VDSO code we can find the g.
        // If we don't have a signal stack, we won't receive signal,
        // so don't bother saving g.
+       // When using cgo, we already saved g on TLS, also don't save
+       // g here.
+       MOVBU   runtime·iscgo(SB), R22
+       CBNZ    R22, nosaveg
        MOVD    m_gsignal(R21), R22          // g.m.gsignal
-       CBZ     R22, 3(PC)
+       CBZ     R22, nosaveg
        MOVD    (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo
        MOVD    g, (R22)
 
        BL      (R2)
 
-       CBZ     R22, 2(PC) // R22 is unchanged by C code
-       MOVD    ZR, (R22)  // clear g slot
+       MOVD    ZR, (R22)  // clear g slot, R22 is unchanged by C code
 
        B       finish
 
+nosaveg:
+       BL      (R2)
+       B       finish
+
 fallback:
        MOVD    $SYS_clock_gettime, R8
        SVC
@@ -294,18 +301,25 @@ noswitch:
        // during VDSO code we can find the g.
        // If we don't have a signal stack, we won't receive signal,
        // so don't bother saving g.
+       // When using cgo, we already saved g on TLS, also don't save
+       // g here.
+       MOVBU   runtime·iscgo(SB), R22
+       CBNZ    R22, nosaveg
        MOVD    m_gsignal(R21), R22          // g.m.gsignal
-       CBZ     R22, 3(PC)
+       CBZ     R22, nosaveg
        MOVD    (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo
        MOVD    g, (R22)
 
        BL      (R2)
 
-       CBZ     R22, 2(PC) // R22 is unchanged by C code
-       MOVD    ZR, (R22)  // clear g slot
+       MOVD    ZR, (R22)  // clear g slot, R22 is unchanged by C code
 
        B       finish
 
+nosaveg:
+       BL      (R2)
+       B       finish
+
 fallback:
        MOVD    $SYS_clock_gettime, R8
        SVC