2010/11/2 Daniel P. Berrange <berrange@xxxxxxxxxx>: > 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list