runtime/cgo: initialize our pthread_create wrapper earlier on openbsd
This is a genuine bug exposed by our test for issue 9456: our wrapper
for pthread_create is not initialized until we initialize cgo itself,
but it is possible that a static constructor could call pthread_create,
and in that case, it will be calling a nil function pointer.
Fix that by also initializing the sys_pthread_create function pointer
inside our pthread_create wrapper function, and use a pthread_once to
make sure it is only initialized once.
Fix build for openbsd.
Change-Id: Ica4da2c21fcaec186fdd3379128ef46f0e767ed7
Reviewed-on: https://go-review.googlesource.com/2232
Reviewed-by: David Crawshaw <crawshaw@golang.org>
diff --git a/src/runtime/cgo/gcc_openbsd_amd64.c b/src/runtime/cgo/gcc_openbsd_amd64.c
index 35b359b..8522cd4 100644
--- a/src/runtime/cgo/gcc_openbsd_amd64.c
+++ b/src/runtime/cgo/gcc_openbsd_amd64.c
@@ -65,12 +65,39 @@
return args.func(args.arg);
}
+static void init_pthread_wrapper(void) {
+ void *handle;
+
+ // Locate symbol for the system pthread_create function.
+ handle = dlopen("libpthread.so", RTLD_LAZY);
+ if(handle == NULL) {
+ fprintf(stderr, "runtime/cgo: dlopen failed to load libpthread: %s\n", dlerror());
+ abort();
+ }
+ sys_pthread_create = dlsym(handle, "pthread_create");
+ if(sys_pthread_create == NULL) {
+ fprintf(stderr, "runtime/cgo: dlsym failed to find pthread_create: %s\n", dlerror());
+ abort();
+ }
+ dlclose(handle);
+}
+
+static pthread_once_t init_pthread_wrapper_once = PTHREAD_ONCE_INIT;
+
int
pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg)
{
struct thread_args *p;
+ // we must initialize our wrapper in pthread_create, because it is valid to call
+ // pthread_create in a static constructor, and in fact, our test for issue 9456
+ // does just that.
+ if(pthread_once(&init_pthread_wrapper_once, init_pthread_wrapper) != 0) {
+ fprintf(stderr, "runtime/cgo: failed to initialize pthread_create wrapper\n");
+ abort();
+ }
+
p = malloc(sizeof(*p));
if(p == NULL) {
errno = ENOMEM;
@@ -87,7 +114,6 @@
{
pthread_attr_t attr;
size_t size;
- void *handle;
setg_gcc = setg;
pthread_attr_init(&attr);
@@ -95,18 +121,10 @@
g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr);
- // Locate symbol for the system pthread_create function.
- handle = dlopen("libpthread.so", RTLD_LAZY);
- if(handle == NULL) {
- fprintf(stderr, "dlopen: failed to load libpthread: %s\n", dlerror());
+ if(pthread_once(&init_pthread_wrapper_once, init_pthread_wrapper) != 0) {
+ fprintf(stderr, "runtime/cgo: failed to initialize pthread_create wrapper\n");
abort();
}
- sys_pthread_create = dlsym(handle, "pthread_create");
- if(sys_pthread_create == NULL) {
- fprintf(stderr, "dlsym: failed to find pthread_create: %s\n", dlerror());
- abort();
- }
- dlclose(handle);
tcb_fixup(1);
}