Update.
authorUlrich Drepper <drepper@redhat.com>
Mon, 16 Oct 2000 21:14:45 +0000 (21:14 +0000)
committerUlrich Drepper <drepper@redhat.com>
Mon, 16 Oct 2000 21:14:45 +0000 (21:14 +0000)
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>.

linuxthreads/ChangeLog
linuxthreads/specific.c

index f863f66..9d34e33 100644 (file)
@@ -1,3 +1,10 @@
+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>.
+
 2000-10-12  Alan Modra <alan@linuxcare.com.au>
 
        * sysdeps/pthread/bits/initspin.h: New file.
index 0c302d4..10697af 100644 (file)
@@ -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. */