aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libstrongswan/threading/windows/thread.c74
-rw-r--r--src/libstrongswan/threading/windows/thread.h9
-rw-r--r--src/libstrongswan/threading/windows/thread_value.c8
3 files changed, 51 insertions, 40 deletions
diff --git a/src/libstrongswan/threading/windows/thread.c b/src/libstrongswan/threading/windows/thread.c
index 2b273413c..8792237e6 100644
--- a/src/libstrongswan/threading/windows/thread.c
+++ b/src/libstrongswan/threading/windows/thread.c
@@ -246,36 +246,6 @@ void* thread_tls_remove(void *key)
}
/**
- * 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
*/
typedef struct {
@@ -634,6 +604,50 @@ void thread_exit(void *val)
ExitThread(0);
}
+/**
+ * Clean up thread data while it detaches
+ */
+static void cleanup_tls()
+{
+ private_thread_t *this;
+ bool old;
+
+ old = set_leak_detective(FALSE);
+ threads_lock->lock(threads_lock);
+
+ this = threads->remove(threads, (void*)(uintptr_t)GetCurrentThreadId());
+
+ threads_lock->unlock(threads_lock);
+ set_leak_detective(old);
+
+ if (this)
+ {
+ /* If the thread exited, but has not been joined, it is in terminated
+ * state. We must not mangle it, as we target externally spawned
+ * threads only. */
+ if (!this->terminated && !this->detached)
+ {
+ destroy(this);
+ }
+ }
+}
+
+/**
+ * DllMain called for dll events
+ */
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ switch (fdwReason)
+ {
+ case DLL_THREAD_DETACH:
+ cleanup_tls();
+ break;
+ default:
+ break;
+ }
+ return TRUE;
+}
+
/*
* Described in header.
*/
diff --git a/src/libstrongswan/threading/windows/thread.h b/src/libstrongswan/threading/windows/thread.h
index 3c470522b..965d9690e 100644
--- a/src/libstrongswan/threading/windows/thread.h
+++ b/src/libstrongswan/threading/windows/thread.h
@@ -61,15 +61,6 @@ void* thread_tls_get(void *key);
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.
*
* This is called whenever a thread exits to clean up thread specific data.
diff --git a/src/libstrongswan/threading/windows/thread_value.c b/src/libstrongswan/threading/windows/thread_value.c
index 1dd8a7816..d7bd7e64c 100644
--- a/src/libstrongswan/threading/windows/thread_value.c
+++ b/src/libstrongswan/threading/windows/thread_value.c
@@ -104,7 +104,13 @@ METHOD(thread_value_t, tls_get, void*,
METHOD(thread_value_t, tls_destroy, void,
private_thread_value_t *this)
{
- thread_tls_remove_all(this);
+ entry_t *entry;
+
+ entry = thread_tls_remove(this);
+ if (entry)
+ {
+ thread_tls_cleanup(entry);
+ }
free(this);
}