diff options
author | David 'Digit' Turner <digit@google.com> | 2010-06-28 14:04:20 -0700 |
---|---|---|
committer | David 'Digit' Turner <digit@google.com> | 2010-06-29 17:11:09 -0700 |
commit | 83b47ccbc4066ef19f5d95261d8a892567a7f0a7 (patch) | |
tree | b158e88cd760c02129fe3ae8df26b92522ea3700 | |
parent | 220a991976c5a029a6b8463c10040c322218934b (diff) | |
download | extras-83b47ccbc4066ef19f5d95261d8a892567a7f0a7.tar.gz |
bionic: add tests for sem_post() and static C++ destruction on dlclose().
Change-Id: I95e5608240881a3880874ea0ae8a24e716186e7f
-rw-r--r-- | tests/bionic/libc/Android.mk | 16 | ||||
-rw-r--r-- | tests/bionic/libc/bionic/libdlclosetest1.cpp | 82 | ||||
-rw-r--r-- | tests/bionic/libc/bionic/test_dlclose_destruction.c | 85 | ||||
-rw-r--r-- | tests/bionic/libc/common/test_sem_post.c | 98 |
4 files changed, 281 insertions, 0 deletions
diff --git a/tests/bionic/libc/Android.mk b/tests/bionic/libc/Android.mk index f68d68b9..48748508 100644 --- a/tests/bionic/libc/Android.mk +++ b/tests/bionic/libc/Android.mk @@ -68,6 +68,7 @@ sources := \ common/test_pthread_mutex.c \ common/test_pthread_once.c \ common/test_semaphore.c \ + common/test_sem_post.c \ common/test_seteuid.c \ common/test_static_cpp_mutex.cpp \ common/test_strftime_2039.c \ @@ -150,6 +151,21 @@ LOCAL_MODULE := test_static_init LOCAL_SHARED_LIBRARIES := libtest_static_init include $(BUILD_EXECUTABLE) +# This test tries to see if static destructors are called +# on dlclose(). We thus need to generate a C++ shared library +include $(CLEAR_VARS) +LOCAL_SRC_FILES := bionic/libdlclosetest1.cpp +LOCAL_MODULE := libdlclosetest1 +LOCAL_PRELINK_MODULE := false +include $(BUILD_SHARED_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_SRC_FILES := bionic/test_dlclose_destruction.c +LOCAL_MODULE := test_dlclose_destruction +LOCAL_LDFLAGS := -ldl +#LOCAL_SHARED_LIBRARIES := libdlclosetest1 +include $(BUILD_EXECUTABLE) + # Testing 'clone' is only possible on Linux systems include $(CLEAR_VARS) LOCAL_SRC_FILES := common/test_clone.c diff --git a/tests/bionic/libc/bionic/libdlclosetest1.cpp b/tests/bionic/libc/bionic/libdlclosetest1.cpp new file mode 100644 index 00000000..d19b6394 --- /dev/null +++ b/tests/bionic/libc/bionic/libdlclosetest1.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <stdio.h> + +class Foo { +public: + Foo(); + virtual ~Foo(); +}; + + +/* This library is used to ensure that static C++ construction + * and destruction operate normally on dlopen() and dlclose(). + * + * We use a global variable inside the DLL called "x" + * and initialize it to 1 in the static C++ constructor. + * + * The main program can access its address through dlsym() + * then later check that it was properly initialized. + */ +extern "C" int x; +int x = 0; + +Foo::Foo() +{ + x = 1; + fprintf(stderr, "%s: setting x to 1\n", __FUNCTION__); +} + +/* Similarly, the main program can provide the address of + * an integer, named "y", that will be set to 2 when the + * static C++ destructor is called on dlclose(). + * + * This address must be provided through the "set_y" function + * that can also be resolved through dlsym() by the program. + */ +static int *to_y = NULL; + +Foo::~Foo() +{ + if (to_y == NULL) { + fprintf(stderr, "%s: to_y uinitialized !!\n", __FUNCTION__); + *(int *)NULL = 0; // crash + } + *to_y = 2; + fprintf(stderr, "%s: setting y(%p) to 2 !\n", __FUNCTION__, to_y); +} + +static Foo f; + +extern "C" +void set_y(int *y) +{ + to_y = y; + fprintf(stderr, "%s: setting to_y=%p\n", __FUNCTION__, y); +} diff --git a/tests/bionic/libc/bionic/test_dlclose_destruction.c b/tests/bionic/libc/bionic/test_dlclose_destruction.c new file mode 100644 index 00000000..fac6a867 --- /dev/null +++ b/tests/bionic/libc/bionic/test_dlclose_destruction.c @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* this program is used to check that static C++ destructors are + * properly called when dlclose() is called. We do this by using + * a helper C++ shared library. + * + * See libdlclosetest1.cpp for details. + */ +#include <dlfcn.h> +#include <stdio.h> + +int main(void) +{ + void* lib = dlopen("libdlclosetest1.so", RTLD_NOW); + int* to_x; + void (*set_y)(int *); + int y = 0; + + if (lib == NULL) { + fprintf(stderr, "Could not load shared library: %s\n", dlerror()); + return 1; + } + + fprintf(stderr, "Loaded !!\n"); + + to_x = dlsym(lib, "x"); + if (to_x == NULL) { + fprintf(stderr, "Could not access global DLL variable (x): %s\n", dlerror()); + return 10; + } + + if (*to_x != 1) { + fprintf(stderr, "Static C++ constructor was not run on dlopen() !\n"); + return 11; + } + + set_y = dlsym(lib, "set_y"); + if (set_y == NULL) { + fprintf(stderr, "Could not access global DLL function (set_y): %s\n", dlerror()); + return 12; + } + + y = 0; + (*set_y)(&y); + + if (dlclose(lib) < 0) { + fprintf(stderr, "Could not unload shared library: %s\n", dlerror()); + return 2; + } + + fprintf(stderr, "Unloaded !!\n"); + + if (y != 2) { + fprintf(stderr, "Static C++ destructor was not run on dlclose() !\n"); + return 11; + } + + return 0; +} diff --git a/tests/bionic/libc/common/test_sem_post.c b/tests/bionic/libc/common/test_sem_post.c new file mode 100644 index 00000000..adc0f859 --- /dev/null +++ b/tests/bionic/libc/common/test_sem_post.c @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* This program is used to test that sem_post() will wake up all + * threads that are waiting on a single semaphore, and not all of + * them. + */ + +#include <pthread.h> +#include <semaphore.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> + +static sem_t semaphore; + +/* Thread function, just wait for the semaphore */ +static void* +thread_func(void* arg) +{ + sem_t *psem = (sem_t *)arg; + void *me = (void *)pthread_self(); + printf("thread %p waiting\n", me); + sem_wait(psem); + printf("thread %p exiting\n", me); + return me; +} + +#define MAX_THREADS 50 + +int main(void) +{ + pthread_t t[MAX_THREADS]; + int nn, value; + + /* Initialize to 1, first thread will exit immediately. + * this is used to exercize more of the semaphore code path */ + if ( sem_init( &semaphore, 0, 1 ) < 0 ) { + printf( "Could not initialize semaphore: %s\n", strerror(errno) ); + return 1; + } + + for ( nn = 0; nn < MAX_THREADS; nn++ ) { + if ( pthread_create( &t[nn], NULL, thread_func, &semaphore ) < 0 ) { + printf("Could not create thread %d: %s\n", nn+1, strerror(errno) ); + return 2; + } + } + sleep( 1 ); + + for (nn = 0; nn < MAX_THREADS; nn++) { + sem_post(&semaphore); + } + + for ( nn = 0; nn < MAX_THREADS; nn++) { + void* result; + pthread_join(t[nn], &result); + if (result != (void*)t[nn]) { + printf("Thread %p joined but returned %p\n", (void*)t[nn], result); + } + } + + if (sem_getvalue(&semaphore, &value) < 0) { + printf("Could not get semaphore value: %s\n", strerror(errno)); + return 3; + } + if (value != 1) { + printf("Error: Semaphore value = %d\n", value); + return 4; + } + return 0; +} |