diff options
author | Ulrich Drepper <drepper@redhat.com> | 2000-10-16 21:14:45 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2000-10-16 21:14:45 +0000 |
commit | 6a14016e3cab30500ce7f88061357c987924fbb0 (patch) | |
tree | 09199438e22bdb5605211ebb1f1225762533ac1e /linuxthreads/specific.c | |
parent | 4abef27cb7e388aed0027ed2b7d989f1833d5999 (diff) | |
download | glibc-6a14016e3cab30500ce7f88061357c987924fbb0.tar glibc-6a14016e3cab30500ce7f88061357c987924fbb0.tar.gz glibc-6a14016e3cab30500ce7f88061357c987924fbb0.tar.bz2 glibc-6a14016e3cab30500ce7f88061357c987924fbb0.zip |
Update.
2000-10-16 Ulrich Drepper <drepper@redhat.com>
* specific.c: Protect tsd array modification in thread data
structures by getting the thread lock in pthread_key_delete and
__pthread_destroy_specifics.
Patch by Wolfram Gloger <Wolfram.Gloger@dent.med.uni-muenchen.de>.
Diffstat (limited to 'linuxthreads/specific.c')
-rw-r--r-- | linuxthreads/specific.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/linuxthreads/specific.c b/linuxthreads/specific.c index 0c302d4b41..10697af7d4 100644 --- a/linuxthreads/specific.c +++ b/linuxthreads/specific.c @@ -19,6 +19,7 @@ #include <stdlib.h> #include "pthread.h" #include "internals.h" +#include "spinlock.h" /* Table of keys. */ @@ -78,8 +79,13 @@ int pthread_key_delete(pthread_key_t key) th = self; do { /* If the thread already is terminated don't modify the memory. */ - if (!th->p_terminated && th->p_specific[idx1st] != NULL) - th->p_specific[idx1st][idx2nd] = NULL; + if (!th->p_terminated) { + /* pthread_exit() may try to free th->p_specific[idx1st] concurrently. */ + __pthread_lock(THREAD_GETMEM(th, p_lock), self); + if (th->p_specific[idx1st] != NULL) + th->p_specific[idx1st][idx2nd] = NULL; + __pthread_unlock(THREAD_GETMEM(th, p_lock)); + } th = th->p_nextlive; } while (th != self); pthread_mutex_unlock(&pthread_keys_mutex); @@ -151,10 +157,14 @@ void __pthread_destroy_specifics() } } } + __pthread_lock(THREAD_GETMEM(self, p_lock), self); for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++) { - if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL) + if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL) { free(THREAD_GETMEM_NC(self, p_specific[i])); + THREAD_SETMEM_NC(self, p_specific[i], NULL); + } } + __pthread_unlock(THREAD_GETMEM(self, p_lock)); } /* Thread-specific data for libc. */ |