go: misc/cgo/testtls: skip test if C toolchain exhibits known TLS bugs

fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0x1b pc=0xe56e4]

runtime stack:
runtime.throw(0x16739f, 0x2a)
	/workdir/go/src/runtime/panic.go:598 +0x54
runtime.sigpanic()
	/workdir/go/src/runtime/signal_unix.go:372 +0x22c

goroutine 5 [syscall, locked to thread]:
runtime.cgocall(0xe5678, 0x429f78, 0xe5208)
	/workdir/go/src/runtime/cgocall.go:128 +0x64 fp=0x429f60 sp=0x429f48 pc=0x123c0
_/workdir/go/misc/cgo/testtls._Cfunc_getTLS(0x0)
	_cgo_gotypes.go:43 +0x38 fp=0x429f74 sp=0x429f60 pc=0xe5134
_/workdir/go/misc/cgo/testtls.testTLS(0x478120)
	/workdir/go/misc/cgo/testtls/tls.go:21 +0x34 fp=0x429fb0 sp=0x429f74 pc=0xe5214
_/workdir/go/misc/cgo/testtls.TestTLS(0x478120)
	/workdir/go/misc/cgo/testtls/tls_test.go:12 +0x1c fp=0x429fb8 sp=0x429fb0 pc=0xe50ec
testing.tRunner(0x478120, 0x168c34)
	/workdir/go/src/testing/testing.go:791 +0xac fp=0x429fe4 sp=0x429fb8 pc=0xb3074
runtime.goexit()
	/workdir/go/src/runtime/asm_arm.s:840 +0x4 fp=0x429fe4 sp=0x429fe4 pc=0x63184
created by testing.(*T).Run
	/workdir/go/src/testing/testing.go:838 +0x240

goroutine 1 [runnable]:
testing.(*T).Run(0x478120, 0x1604a5, 0x7, 0x168c34, 0x410540)
	/workdir/go/src/testing/testing.go:839 +0x260
testing.runTests.func1(0x478090)
	/workdir/go/src/testing/testing.go:1081 +0x50
testing.tRunner(0x478090, 0x44bef8)
	/workdir/go/src/testing/testing.go:791 +0xac
testing.runTests(0x40c040, 0x206598, 0x1, 0x1, 0x458100)
	/workdir/go/src/testing/testing.go:1079 +0x21c
testing.(*M).Run(0x458100, 0x0)
	/workdir/go/src/testing/testing.go:996 +0x134
main.main()
	_testmain.go:42 +0x12c
exit status 2
FAIL	_/workdir/go/misc/cgo/testtls	0.046s

Some recent occurences:

https://build.golang.org/log/b7e1728e48a73089be64d42ea3b7e581eeae029c https://build.golang.org/log/56a9b6b774c15433baff5b11a2f2eeb8aaa936a1

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Comments: 20 (19 by maintainers)

Most upvoted comments

First, I spent some time rediscovered what I found last year (https://github.com/golang/go/issues/24758#issuecomment-380136983). I should have read all the comments first…

Then, by attaching strace I found that when the test passes the TLS accesses are made on the main thread, whereas when it fails the TLS accesses are made on a non-main thread. (at least for all the runs I investigated.)

If I change the test so that it always run on a non-main thread, it fails 100%. The same change works fine on Linux/AMD64.

On all the test logs, the failed one is the one with static linking (https://go.googlesource.com/go/+/refs/tags/go1.13/src/cmd/dist/test.go#1072). Here, we build the C code with -fPIC, which will generate __tls_get_addr for TLS access. Then we link with -static. On AMD64, this will make the linker patch __tls_get_addr to static TLS access. This doesn’t happen on ARM. From glibc source code (https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/arm/libc-tls.c;h=22ec3b0c194d0315dc87e73126a0f5c71241346e;hb=0f02b6cfc44af73d4d4363c46b3cbb18b8ff9171#l22), it claims that linker patching is not necessary. But it doesn’t seem to be the case.

The following C program fails on ARM but works fine on AMD64:

#include <stdio.h>
#include <pthread.h>

static __thread int x;

void* nonmain() {
	printf("nonmain &x=%p\n", &x);
	printf("nonmain x=%d\n", x);
	return 0;
}

int main() {
	pthread_t t;

	printf("main &x=%p\n", &x);
	printf("main x=%d\n", x);
	pthread_create(&t, 0, nonmain, 0);
	pthread_join(t, 0);
	return 0;
}
# cc -fPIC tls.c -pthread -static
# ./a.out 
main &x=0x844dc
main x=0
nonmain &x=0x13
Segmentation fault (core dumped)

So, it seems that -fPIC and -static just don’t work together on ARM…

BTW, if would be easier if the builder has gdb installed. Could we install gdb there?

I’ll look into this (as soon as I can, maybe not this week though).

This is not my kind of TLS 😉 it’s Thread Local Storage.