]> Cypherpunks repositories - gostls13.git/commitdiff
runtime/cgo: initialize our pthread_create wrapper earlier on openbsd
authorShenghou Ma <minux@golang.org>
Thu, 1 Jan 2015 01:30:57 +0000 (20:30 -0500)
committerMinux Ma <minux@golang.org>
Thu, 1 Jan 2015 02:52:34 +0000 (02:52 +0000)
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>
src/runtime/cgo/gcc_openbsd_386.c
src/runtime/cgo/gcc_openbsd_amd64.c

index 582e943f34c4c8dc900f3e42d6736b82d4971a97..b046bc8bdd69cb2f6887668636291453168dc684 100644 (file)
@@ -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);
 }
index 35b359bbaf3fd6e7df7ecaa4e3f389e8911e7ff1..8522cd48c4ac9fec18e06c53fe850ef91da4d6dc 100644 (file)
@@ -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);
 }