aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBryan C. Mills <bcmills@google.com>2017-08-07 19:30:03 -0400
committerBryan Mills <bcmills@google.com>2017-08-16 18:49:38 +0000
commite0545faf270fdbc0b3864db62f528eb36da3c63f (patch)
tree1214c23536e085230a0e52238f832b843e128d97 /src
parent58f84fdf29ca2f014a813991cf35e52de91a43cb (diff)
downloadgo-e0545faf270fdbc0b3864db62f528eb36da3c63f.tar.xz
runtime/cgo: defeat inlining in x_cgo_yield
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>
Diffstat (limited to 'src')
-rw-r--r--src/runtime/cgo/gcc_util.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/src/runtime/cgo/gcc_util.c b/src/runtime/cgo/gcc_util.c
index 2d5382a8f0..3fcb48cc8d 100644
--- a/src/runtime/cgo/gcc_util.c
+++ b/src/runtime/cgo/gcc_util.c
@@ -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;