1
0
mirror of https://github.com/golang/go synced 2024-11-19 13:04:45 -07:00

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>
This commit is contained in:
Bryan C. Mills 2017-08-07 19:30:03 -04:00 committed by Bryan Mills
parent 58f84fdf29
commit e0545faf27

View 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;