diff options
| author | Bryan C. Mills <bcmills@google.com> | 2017-08-07 19:30:03 -0400 |
|---|---|---|
| committer | Bryan Mills <bcmills@google.com> | 2017-08-16 18:49:38 +0000 |
| commit | e0545faf270fdbc0b3864db62f528eb36da3c63f (patch) | |
| tree | 1214c23536e085230a0e52238f832b843e128d97 /src | |
| parent | 58f84fdf29ca2f014a813991cf35e52de91a43cb (diff) | |
| download | go-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.c | 13 |
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(¬hing, ¬hing, 0); + strncpy(&x_cgo_yield_strncpy_dst, &x_cgo_yield_strncpy_src, + x_cgo_yield_strncpy_n); } void(* const _cgo_yield)() = &x_cgo_yield; |
