aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2014-06-11 14:24:22 +0200
committerMartin Willi <martin@revosec.ch>2014-06-17 15:19:40 +0200
commit23750961d5b9052ddfe6d4746435e84ca0c87a10 (patch)
treeec707ec981b9324072a4532c14dec5ab82a6204c /src
parent2d846c2035de26a52d1439b46b0ca7903fa9dca1 (diff)
downloadstrongswan-23750961d5b9052ddfe6d4746435e84ca0c87a10.tar.bz2
strongswan-23750961d5b9052ddfe6d4746435e84ca0c87a10.tar.xz
thread-value: Defer cleanup handling to thread termination on Windows
Instead of cleaning up all thread-values during destruction, cleanup handler is invoked when a thread detaches. Thread detaching is cough using the Windows DllMain() entry point, and allows us to basically revert 204098a7. Using this mechanism, we make sure that the cleanup handler is invoked by the the correct thread. Further, this mechanism works for externally-spawned threads which run outside of our thread_cb() routine, and works more efficiently with short-running threads.
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);
}