diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libstrongswan/threading/windows/thread.c | 74 | ||||
-rw-r--r-- | src/libstrongswan/threading/windows/thread.h | 9 | ||||
-rw-r--r-- | src/libstrongswan/threading/windows/thread_value.c | 8 |
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); } |