]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
thread-value: Immediately cleanup all Windows TLS values on destroy
authorMartin Willi <martin@revosec.ch>
Fri, 6 Dec 2013 10:33:40 +0000 (11:33 +0100)
committerMartin Willi <martin@revosec.ch>
Wed, 4 Jun 2014 13:53:02 +0000 (15:53 +0200)
src/libstrongswan/threading/windows/thread.c
src/libstrongswan/threading/windows/thread.h
src/libstrongswan/threading/windows/thread_value.c

index 5fa68bb91cf605d21c557e4804e47f25bb03ff0b..35d56c47dfc94a72b2f7ff2ab635077a0ad3759e 100644 (file)
@@ -68,7 +68,7 @@ struct private_thread_t {
        array_t *cleanup;
 
        /**
-        * Thread specific values for this thread, as cleanup_t
+        * Thread specific values for this thread
         */
        hashtable_t *tls;
 
@@ -238,12 +238,44 @@ void* thread_tls_remove(void *key)
        thread = get_current_thread();
 
        old = set_leak_detective(FALSE);
+       threads_lock->lock(threads_lock);
        value = thread->tls->remove(thread->tls, key);
+       threads_lock->unlock(threads_lock);
        set_leak_detective(old);
 
        return value;
 }
 
+/**
+ * See header.
+ */
+void thread_tls_remove_all(void *key)
+{
+       private_thread_t *thread;
+       enumerator_t *enumerator;
+       void *value;
+       bool old;
+
+       old = set_leak_detective(FALSE);
+       threads_lock->lock(threads_lock);
+
+       enumerator = threads->create_enumerator(threads);
+       while (enumerator->enumerate(enumerator, NULL, &thread))
+       {
+               value = thread->tls->remove(thread->tls, key);
+               if (value)
+               {
+                       set_leak_detective(old);
+                       thread_tls_cleanup(value);
+                       set_leak_detective(FALSE);
+               }
+       }
+       enumerator->destroy(enumerator);
+
+       threads_lock->unlock(threads_lock);
+       set_leak_detective(old);
+}
+
 /**
  * Thread cleanup data
  */
@@ -272,6 +304,7 @@ static void docleanup(private_thread_t *this)
                set_leak_detective(FALSE);
        }
 
+       threads_lock->lock(threads_lock);
        enumerator = this->tls->create_enumerator(this->tls);
        while (enumerator->enumerate(enumerator, NULL, &tls))
        {
@@ -282,6 +315,7 @@ static void docleanup(private_thread_t *this)
                set_leak_detective(FALSE);
        }
        enumerator->destroy(enumerator);
+       threads_lock->unlock(threads_lock);
 
        set_leak_detective(old);
 }
index e393d183c1eb90ced4706520a2bf90e13d08cd40..5711717023fa232476e0f1f984767203bae1843e 100644 (file)
@@ -73,11 +73,19 @@ void* thread_tls_get(void *key);
  * Remove a thread specific value from the current thread.
  *
  * @param key          unique key specifying the TLS variable
- * @param value                value to set
- * @return                     old value for key, if any
+ * @return                     value for key, if any
  */
 void* thread_tls_remove(void *key);
 
+/**
+ * Remove a thread specific value from all threads.
+ *
+ * For each found TLS value thread_tls_cleanup() is invoked.
+ *
+ * @param key          unique key specifying the TLS variable
+ */
+void thread_tls_remove_all(void *key);
+
 /**
  * Cleanup function for thread specific value.
  *
index 8ba127fd406754e9edff46d1fc2dad0012bcf43d..da79d7b44ceb7100dad454ecf01906c9ec9ca040 100644 (file)
@@ -105,17 +105,7 @@ METHOD(thread_value_t, tls_get, void*,
 METHOD(thread_value_t, tls_destroy, void,
        private_thread_value_t *this)
 {
-       entry_t *entry;
-
-       entry = thread_tls_remove(this);
-       if (entry)
-       {
-               if (entry->cleanup)
-               {
-                       entry->cleanup(entry->value);
-               }
-               free(entry);
-       }
+       thread_tls_remove_all(this);
        free(this);
 }