From 77cd6197d7561ab7ccbf5d892efb6f97d929546a Mon Sep 17 00:00:00 2001 From: Shenghou Ma Date: Wed, 31 Dec 2014 20:30:57 -0500 Subject: [PATCH] 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 --- src/runtime/cgo/gcc_openbsd_386.c | 39 ++++++++++++++++++++-------- src/runtime/cgo/gcc_openbsd_amd64.c | 40 +++++++++++++++++++++-------- 2 files changed, 58 insertions(+), 21 deletions(-) diff --git a/src/runtime/cgo/gcc_openbsd_386.c b/src/runtime/cgo/gcc_openbsd_386.c index 582e943f34..b046bc8bdd 100644 --- a/src/runtime/cgo/gcc_openbsd_386.c +++ b/src/runtime/cgo/gcc_openbsd_386.c @@ -65,12 +65,39 @@ thread_start_wrapper(void *arg) 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; @@ -95,18 +122,10 @@ x_cgo_init(G *g, void (*setg)(void*)) 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()); - abort(); - } - sys_pthread_create = dlsym(handle, "pthread_create"); - if(sys_pthread_create == NULL) { - fprintf(stderr, "dlsym: failed to find pthread_create: %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(); } - dlclose(handle); tcb_fixup(1); } diff --git a/src/runtime/cgo/gcc_openbsd_amd64.c b/src/runtime/cgo/gcc_openbsd_amd64.c index 35b359bbaf..8522cd48c4 100644 --- a/src/runtime/cgo/gcc_openbsd_amd64.c +++ b/src/runtime/cgo/gcc_openbsd_amd64.c @@ -65,12 +65,39 @@ thread_start_wrapper(void *arg) 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 @@ x_cgo_init(G *g, void (*setg)(void*)) { pthread_attr_t attr; size_t size; - void *handle; setg_gcc = setg; pthread_attr_init(&attr); @@ -95,18 +121,10 @@ x_cgo_init(G *g, void (*setg)(void*)) 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()); - abort(); - } - sys_pthread_create = dlsym(handle, "pthread_create"); - if(sys_pthread_create == NULL) { - fprintf(stderr, "dlsym: failed to find pthread_create: %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(); } - dlclose(handle); tcb_fixup(1); } -- 2.48.1