[vlc-commits] commit: Win32: fix race between vlc_cancel() and vlc_threadvar_set() ( Rémi Denis-Courmont )
git at videolan.org
git at videolan.org
Wed Apr 7 21:10:56 CEST 2010
vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Wed Apr 7 22:10:33 2010 +0300| [120ad81452eeb1353b2739f79731020d9a85b213] | committer: Rémi Denis-Courmont
Win32: fix race between vlc_cancel() and vlc_threadvar_set()
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=120ad81452eeb1353b2739f79731020d9a85b213
---
src/win32/thread.c | 23 ++++++++++++++++-------
1 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/src/win32/thread.c b/src/win32/thread.c
index c41fbc4..dfeed9a 100644
--- a/src/win32/thread.c
+++ b/src/win32/thread.c
@@ -505,6 +505,7 @@ struct vlc_entry_data
{
void * (*func) (void *);
void * data;
+ vlc_sem_t ready;
#ifdef UNDER_CE
HANDLE cancel_event;
#endif
@@ -512,18 +513,17 @@ struct vlc_entry_data
static unsigned __stdcall vlc_entry (void *p)
{
+ struct vlc_entry_data *entry = p;
vlc_cancel_t cancel_data = VLC_CANCEL_INIT;
- struct vlc_entry_data data;
-
- memcpy (&data, p, sizeof (data));
- free (p);
+ void *(*func) (void *) = entry->func;
+ void *data = entry->data;
#ifdef UNDER_CE
- cancel_data.cancel_event = data.cancel_event;
+ cancel_data.cancel_event = entry->cancel_event;
#endif
-
vlc_threadvar_set (cancel_key, &cancel_data);
- data.func (data.data);
+ vlc_sem_post (&entry->ready);
+ func (data);
return 0;
}
@@ -538,6 +538,7 @@ int vlc_clone (vlc_thread_t *p_handle, void * (*entry) (void *), void *data,
return ENOMEM;
entry_data->func = entry;
entry_data->data = data;
+ vlc_sem_init (&entry_data->ready, 0);
#ifndef UNDER_CE
/* When using the MSVCRT C library you have to use the _beginthreadex
@@ -594,9 +595,17 @@ int vlc_clone (vlc_thread_t *p_handle, void * (*entry) (void *), void *data,
if (priority)
SetThreadPriority (hThread, priority);
+ /* Prevent cancellation until cancel_data is initialized. */
+ /* XXX: This could be postponed to vlc_cancel() or avoided completely by
+ * passing the "right" pointer to vlc_cancel_self(). */
+ vlc_sem_wait (&entry_data->ready);
+ vlc_sem_destroy (&entry_data->ready);
+ free (entry_data);
+
return 0;
error:
+ vlc_sem_destroy (&entry_data->ready);
free (entry_data);
return err;
}
More information about the vlc-commits
mailing list