
2010/11/2 Daniel P. Berrange <berrange@redhat.com>:
The util/threads.c/h code already has APIs for mutexes, condition variables and thread locals. This commit adds in code for actually creating threads.
+ +void virThreadSelf(virThreadPtr thread) +{ + thread->thread = pthread_self(); +} + +bool virThreadIsSelf(virThreadPtr thread) +{ + return pthread_self() == thread->thread ? true : false; +}
The pthread_self manpage says that it's not safe to compare pthread_t's using == and advises to use pthread_equal for this.
+ +void virThreadJoin(virThreadPtr thread) +{ + pthread_join(thread->thread, NULL); +}
int virThreadLocalInit(virThreadLocalPtr l, virThreadLocalCleanup c)
diff --git a/src/util/threads-win32.c b/src/util/threads-win32.c index fe1fcd0..3f69f41 100644 --- a/src/util/threads-win32.c +++ b/src/util/threads-win32.c @@ -21,6 +21,8 @@
#include <config.h>
+#include <process.h> + #include "memory.h"
struct virThreadLocalData { @@ -205,6 +207,51 @@ void virCondBroadcast(virCondPtr c) }
+struct virThreadArgs { + virThreadFunc func; + void *opaque; +}; + +static unsigned int __stdcall virThreadHelper(void *data) +{ + struct virThreadArgs *args = data; + args->func(args->opaque); + return 0; +} + +int virThreadCreate(virThreadPtr thread, + bool joinable ATTRIBUTE_UNUSED, + virThreadFunc func, + void *opaque) +{ + struct virThreadArgs args = { func, opaque }; + thread->thread = (HANDLE)_beginthreadex(NULL, 0, virThreadHelper, &args, 0, NULL); + return 0; +}
When you create a non-joinable thread then you won't call virThreadJoin on it and you''ll leak the handle. Therefore, we should use _beginthread here instead of _beginthreadex when creating a non-joinable thread, because _endthread will close the thread's handle when the thread's function returns. See http://msdn.microsoft.com/en-us/library/kdzttdcb(VS.71).aspx
+ +void virThreadSelf(virThreadPtr thread) +{ + HANDLE handle = GetCurrentThread(); + HANDLE process = GetCurrentProcess(); + + DuplicateHandle(process, handle, process, + &thread->thread, 0, FALSE, + DUPLICATE_SAME_ACCESS); +}
If virThreadJoin is not called on virThreadPtr initialized by virThreadSelf then the duplicated handle leaks. See http://msdn.microsoft.com/en-us/library/ms683182(VS.85).aspx
+bool virThreadIsSelf(virThreadPtr thread) +{ + virThread self; + virThreadSelf(&self); + return self.thread == thread->thread ? true : false; +}
Therefore, this definitely leaks a handle per call.
+void virThreadJoin(virThreadPtr thread) +{ + WaitForSingleObject(thread->thread, INFINITE); + CloseHandle(thread->thread); +} +
This might create really subtle double-CloseHandle bugs when you call it twice on the same virThreadPtr or call it accidentally on an non-joinable thread that already exited and _endthread had close the handle. In both cases Windows might already reused the closed handle and the second call to CloseHandle might close something completely unrelated. Matthias