Re: [PATCH 07/11] Introduce portability APIs for creating threads

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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



[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]