aboutsummaryrefslogtreecommitdiff
path: root/linuxthreads/specific.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2000-10-16 21:14:45 +0000
committerUlrich Drepper <drepper@redhat.com>2000-10-16 21:14:45 +0000
commit6a14016e3cab30500ce7f88061357c987924fbb0 (patch)
tree09199438e22bdb5605211ebb1f1225762533ac1e /linuxthreads/specific.c
parent4abef27cb7e388aed0027ed2b7d989f1833d5999 (diff)
downloadglibc-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.c16
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. */