1
0
mirror of https://github.com/golang/go synced 2024-11-19 03:44:40 -07:00

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>
This commit is contained in:
Shenghou Ma 2014-12-31 20:30:57 -05:00 committed by Minux Ma
parent 76b2f06ee5
commit 77cd6197d7
2 changed files with 58 additions and 21 deletions

View File

@ -65,12 +65,39 @@ thread_start_wrapper(void *arg)
return args.func(args.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 int
pthread_create(pthread_t *thread, const pthread_attr_t *attr, pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg) void *(*start_routine)(void *), void *arg)
{ {
struct thread_args *p; 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)); p = malloc(sizeof(*p));
if(p == NULL) { if(p == NULL) {
errno = ENOMEM; errno = ENOMEM;
@ -95,18 +122,10 @@ x_cgo_init(G *g, void (*setg)(void*))
g->stacklo = (uintptr)&attr - size + 4096; g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr); pthread_attr_destroy(&attr);
// Locate symbol for the system pthread_create function. if(pthread_once(&init_pthread_wrapper_once, init_pthread_wrapper) != 0) {
handle = dlopen("libpthread.so", RTLD_LAZY); fprintf(stderr, "runtime/cgo: failed to initialize pthread_create wrapper\n");
if(handle == NULL) {
fprintf(stderr, "dlopen: failed to load libpthread: %s\n", dlerror());
abort(); 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); tcb_fixup(1);
} }

View File

@ -65,12 +65,39 @@ thread_start_wrapper(void *arg)
return args.func(args.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 int
pthread_create(pthread_t *thread, const pthread_attr_t *attr, pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg) void *(*start_routine)(void *), void *arg)
{ {
struct thread_args *p; 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)); p = malloc(sizeof(*p));
if(p == NULL) { if(p == NULL) {
errno = ENOMEM; errno = ENOMEM;
@ -87,7 +114,6 @@ x_cgo_init(G *g, void (*setg)(void*))
{ {
pthread_attr_t attr; pthread_attr_t attr;
size_t size; size_t size;
void *handle;
setg_gcc = setg; setg_gcc = setg;
pthread_attr_init(&attr); pthread_attr_init(&attr);
@ -95,18 +121,10 @@ x_cgo_init(G *g, void (*setg)(void*))
g->stacklo = (uintptr)&attr - size + 4096; g->stacklo = (uintptr)&attr - size + 4096;
pthread_attr_destroy(&attr); pthread_attr_destroy(&attr);
// Locate symbol for the system pthread_create function. if(pthread_once(&init_pthread_wrapper_once, init_pthread_wrapper) != 0) {
handle = dlopen("libpthread.so", RTLD_LAZY); fprintf(stderr, "runtime/cgo: failed to initialize pthread_create wrapper\n");
if(handle == NULL) {
fprintf(stderr, "dlopen: failed to load libpthread: %s\n", dlerror());
abort(); 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); tcb_fixup(1);
} }