diff options
-rw-r--r-- | sysdeps/hurd/pt-key-delete.c | 19 | ||||
-rw-r--r-- | tests/Makefile | 2 | ||||
-rw-r--r-- | tests/test-17.c | 57 |
3 files changed, 77 insertions, 1 deletions
diff --git a/sysdeps/hurd/pt-key-delete.c b/sysdeps/hurd/pt-key-delete.c index 2426bb11..9d88647e 100644 --- a/sysdeps/hurd/pt-key-delete.c +++ b/sysdeps/hurd/pt-key-delete.c @@ -35,8 +35,27 @@ pthread_key_delete (pthread_key_t key) err = EINVAL; else { + int i; + __pthread_key_destructors[key] = PTHREAD_KEY_INVALID; __pthread_key_invalid_count ++; + + pthread_rwlock_rdlock (&__pthread_threads_lock); + for (i = 0; i < __pthread_num_threads; ++i) + { + struct __pthread *t; + + t = __pthread_threads[i]; + + if (t == NULL) + continue; + + /* Just remove the key, no need to care whether it was + already there. */ + if (t->thread_specifics) + hurd_ihash_remove (t->thread_specifics, key); + } + pthread_rwlock_unlock (&__pthread_threads_lock); } __pthread_mutex_unlock (&__pthread_key_lock); diff --git a/tests/Makefile b/tests/Makefile index 343a6446..5ebc01d3 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -4,7 +4,7 @@ LDLIBS = -lpthread CHECK_SRC := test-1.c test-2.c test-3.c test-6.c test-7.c test-8.c \ test-9.c test-10.c test-11.c test-12.c test-13.c test-14.c \ - test-15.c test-16.c test-__pthread_destroy_specific-skip.c + test-15.c test-16.c test-17.c test-__pthread_destroy_specific-skip.c CHECK_OBJS := $(addsuffix .o,$(basename $(notdir $(CHECK_SRC)))) CHECK_PROGS := $(basename $(notdir $(CHECK_SRC))) \ diff --git a/tests/test-17.c b/tests/test-17.c new file mode 100644 index 00000000..a8bd1503 --- /dev/null +++ b/tests/test-17.c @@ -0,0 +1,57 @@ +/* Test that the key reuse inside libpthread does not cause thread + specific values to persist. */ + +#define _GNU_SOURCE 1 + +#include <pthread.h> +#include <stdio.h> +#include <assert.h> +#include <errno.h> + +void +work (int iter) +{ + error_t err; + pthread_key_t key1; + pthread_key_t key2; + void *value1; + void *value2; + + printf ("work/%d: start\n", iter); + err = pthread_key_create (&key1, NULL); + assert (err == 0); + err = pthread_key_create (&key2, NULL); + assert (err == 0); + + value1 = pthread_getspecific (key1); + value2 = pthread_getspecific (key2); + printf ("work/%d: pre-setspecific: %p,%p\n", iter, value1, value2); + assert (value1 == NULL); + assert (value2 == NULL); + err = pthread_setspecific (key1, (void *)(0x100 + iter)); + assert (err == 0); + err = pthread_setspecific (key2, (void *)(0x200 + iter)); + assert (err == 0); + + value1 = pthread_getspecific (key1); + value2 = pthread_getspecific (key2); + printf ("work/%d: post-setspecific: %p,%p\n", iter, value1, value2); + assert (value1 == (void *)(0x100 + iter)); + assert (value2 == (void *)(0x200 + iter)); + + err = pthread_key_delete (key1); + assert (err == 0); + err = pthread_key_delete (key2); + assert (err == 0); +} + +int +main (int argc, char *argv[]) +{ + int i; + + for (i = 0; i < 8; ++i) + work (i + 1); + + return 0; +} |