]> Cypherpunks repositories - gostls13.git/commitdiff
runtime/cgo: defeat inlining in x_cgo_yield
authorBryan C. Mills <bcmills@google.com>
Mon, 7 Aug 2017 23:30:03 +0000 (19:30 -0400)
committerBryan Mills <bcmills@google.com>
Wed, 16 Aug 2017 18:49:38 +0000 (18:49 +0000)
We use a call to strncpy to work around a TSAN bug (wherein TSAN only
delivers asynchronous signals when the thread receiving the signal
calls a libc function). Unfortunately, GCC 7 inlines the call,
avoiding the TSAN libc trap entirely.

Per Ian's suggestion, use global variables as strncpy arguments: that
way, the compiler can't make any assumptions about the concrete values
and can't inline the call away.

fixes #21196

Change-Id: Ie95f1feaf9af1a8056f924f49c29cfc8515385d7
Reviewed-on: https://go-review.googlesource.com/55872
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/runtime/cgo/gcc_util.c

index 2d5382a8f09b6916c3af1a52426a2a39227807f9..3fcb48cc8d5a4252d6ce9a65a61f00855e0adce6 100644 (file)
@@ -29,6 +29,10 @@ void(* const _cgo_yield)() = NULL;
 
 #include <string.h>
 
+char x_cgo_yield_strncpy_src = 0;
+char x_cgo_yield_strncpy_dst = 0;
+size_t x_cgo_yield_strncpy_n = 0;
+
 /*
 Stub for allowing libc interceptors to execute.
 
@@ -50,9 +54,14 @@ x_cgo_yield()
 
        So we choose strncpy(_, _, 0): it requires an extra header,
        but it's standard and should be very efficient.
+
+       GCC 7 has an unfortunate habit of optimizing out strncpy calls (see
+       https://golang.org/issue/21196), so the arguments here need to be global
+       variables with external linkage in order to ensure that the call traps all the
+       way down into libc.
        */
-       char nothing = 0;
-       strncpy(&nothing, &nothing, 0);
+       strncpy(&x_cgo_yield_strncpy_dst, &x_cgo_yield_strncpy_src,
+               x_cgo_yield_strncpy_n);
 }
 
 void(* const _cgo_yield)() = &x_cgo_yield;