Fix is similar to libpthread.  Also, use the spinlock and verify that key
has a valid value, the implementation is too flexible right now.  (I
realize now that libpthread should also check for key < 0, I'll have to
go back and fix that too.)

Index: rthread_tls.c
===================================================================
RCS file: /home/tedu/cvs/src/lib/librthread/rthread_tls.c,v
retrieving revision 1.11
diff -u -r1.11 rthread_tls.c
--- rthread_tls.c       13 Oct 2008 05:42:46 -0000      1.11
+++ rthread_tls.c       2 Jul 2011 15:21:24 -0000
@@ -71,16 +71,33 @@
 int
 pthread_key_delete(pthread_key_t key)
 {
+       pthread_t thread;
+       struct rthread_storage *rs;
+       int rv = 0;
 
-       if (!rkeys[key].used)
+       if (key < 0 || key >= PTHREAD_KEYS_MAX)
                return (EINVAL);
 
        _spinlock(&rkeyslock);
+       if (!rkeys[key].used) {
+               rv = EINVAL;
+               goto out;
+       }
+
        rkeys[key].used = 0;
        rkeys[key].destructor = NULL;
-       _spinunlock(&rkeyslock);
+       _spinlock(&_thread_lock);
+       LIST_FOREACH(thread, &_thread_list, threads) {
+               for (rs = thread->local_storage; rs; rs = rs->next) {
+                       if (rs->keyid == key)
+                               rs->data = NULL;
+               }
+       }
+       _spinunlock(&_thread_lock);
 
-       return (0);
+out:
+       _spinunlock(&rkeyslock);
+       return (rv);
 }
 
 static struct rthread_storage *
@@ -89,6 +106,12 @@
        struct rthread_storage *rs;
        pthread_t self;
 
+       _spinlock(&rkeyslock);
+       if (!rkeys[key].used) {
+               rs = NULL;
+               goto out;
+       }
+
        self = pthread_self();
 
        for (rs = self->local_storage; rs; rs = rs->next) {
@@ -98,13 +121,15 @@
        if (!rs) {
                rs = calloc(1, sizeof(*rs));
                if (!rs)
-                       return (NULL);
+                       goto out;
                rs->keyid = key;
                rs->data = NULL;
                rs->next = self->local_storage;
                self->local_storage = rs;
        }
 
+out:
+       _spinunlock(&rkeyslock);
        return (rs);
 }
 
@@ -113,6 +138,9 @@
 {
        struct rthread_storage *rs;
 
+       if (key < 0 || key >= PTHREAD_KEYS_MAX)
+               return (NULL);
+
        rs = _rthread_findstorage(key);
        if (!rs)
                return (NULL);
@@ -124,6 +152,9 @@
 pthread_setspecific(pthread_key_t key, const void *data)
 {
        struct rthread_storage *rs;
+
+       if (key < 0 || key >= PTHREAD_KEYS_MAX)
+               return (EINVAL);
 
        rs = _rthread_findstorage(key);
        if (!rs)

Reply via email to