[vlc-devel] [PATCH 1/2] core: win32: Add a vlc_mta_holder

Rémi Denis-Courmont remi at remlab.net
Wed Jun 7 12:57:28 CEST 2017


On June 7, 2017 11:58:22 AM GMT+03:00, "Hugo Beauzée-Luyssen" <hugo at beauzee.fr> wrote:
>This small helper will hold on to the MTA to ensure it won't be
>destroyed between two calls to CoInitializeEx.
>This will help us not leaking our TA configurations to
>libvlc/libvlccore
>threads
>
>Changes since previous patch:
>- Fix potential race condition
>- Do not export the functions on !_WIN32
>---
> include/vlc_threads.h  |  20 +++++++++
> src/Makefile.am        |   3 +-
> src/libvlccore.sym     |   2 +
>src/win32/mta_holder.c | 114
>+++++++++++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 138 insertions(+), 1 deletion(-)
> create mode 100644 src/win32/mta_holder.c
>
>diff --git a/include/vlc_threads.h b/include/vlc_threads.h
>index 9911d2eacf..44b57f1255 100644
>--- a/include/vlc_threads.h
>+++ b/include/vlc_threads.h
>@@ -46,6 +46,8 @@
>  */
> VLC_API void vlc_testcancel(void);
> 
>+typedef struct vlc_mta_holder vlc_mta_holder;
>+
> #if defined (_WIN32)
> # include <process.h>
> # ifndef ETIMEDOUT
>@@ -946,6 +948,24 @@ VLC_API unsigned vlc_timer_getoverrun(vlc_timer_t)
>VLC_USED;
>  */
> VLC_API unsigned vlc_GetCPUCount(void);
> 
>+/**
>+ * Ensure an MTA context will be available until vlc_mta_release gets
>called.
>+ *
>+ * In the background, this will create a thread that does nothing but
>to keep the MTA
>+ * refcount greater than 0.
>+ *
>+ * This is usefull in order not to commit a thread to a specific
>concurrency model.
>+ * This function is win32 specific.
>+ */
>+VLC_API vlc_mta_holder* vlc_mta_acquire( vlc_object_t* p_obj );
>+
>+/**
>+ * Releases a reference to the MTA holder.
>+ *
>+ * When its refcount reaches 0, the thread created by
>+ */
>+VLC_API void vlc_mta_release( vlc_mta_holder* p_mta );
>+
> enum
> {
>     VLC_CLEANUP_PUSH,
>diff --git a/src/Makefile.am b/src/Makefile.am
>index 5f3726c3e6..f412287bd9 100644
>--- a/src/Makefile.am
>+++ b/src/Makefile.am
>@@ -358,6 +358,7 @@ libvlccore_la_SOURCES += \
> 	win32/dirs.c \
> 	win32/error.c \
> 	win32/filesystem.c \
>+	win32/mta_holder.c \
> 	win32/netconf.c \
> 	win32/plugin.c \
> 	win32/rand.c \
>@@ -467,7 +468,7 @@ libvlccore_la_LDFLAGS = \
> libvlccore_la_DEPENDENCIES = libvlccore.sym
> if HAVE_WIN32
> libvlccore_la_DEPENDENCIES += libvlc_win32_rc.$(OBJEXT)
>-libvlccore_la_LDFLAGS += -Wl,libvlc_win32_rc.$(OBJEXT) -avoid-version
>-Wc,-static
>+libvlccore_la_LDFLAGS += -Wl,libvlc_win32_rc.$(OBJEXT) -avoid-version
>-Wc,-static $(LIBCOM)
> endif
> if HAVE_OS2
> libvlccore_la_LDFLAGS += -avoid-version
>diff --git a/src/libvlccore.sym b/src/libvlccore.sym
>index bc21ee682c..88ef871427 100644
>--- a/src/libvlccore.sym
>+++ b/src/libvlccore.sym
>@@ -752,3 +752,5 @@ vlc_rd_get_names
> vlc_rd_new
> vlc_rd_release
> vlc_rd_probe_add
>+vlc_mta_acquire
>+vlc_mta_release
>diff --git a/src/win32/mta_holder.c b/src/win32/mta_holder.c
>new file mode 100644
>index 0000000000..42e945ea52
>--- /dev/null
>+++ b/src/win32/mta_holder.c
>@@ -0,0 +1,114 @@
>+/*****************************************************************************
>+ * mta_holder.c: Hold a MTA from another thread
>+
>*****************************************************************************
>+ * Copyright (C) 2002-2017 the VideoLAN and AUTHORS
>+ *
>+ * Author: Hugo Beauzée-Luyssen <hugo at beauzee.fr>
>+ *
>+ * This program is free software; you can redistribute it and/or
>modify
>+ * it under the terms of the GNU General Public License as published
>by
>+ * the Free Software Foundation; either version 2 of the License, or
>+ * (at your option) any later version.
>+ *
>+ * This program is distributed in the hope that it will be useful,
>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>+ * GNU General Public License for more details.
>+ *
>+ * You should have received a copy of the GNU General Public License
>+ * along with this program; if not, write to the Free Software
>+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA
>02110-1301, USA.
>+
>*****************************************************************************/
>+
>+#ifdef HAVE_CONFIG_H
>+# include "config.h"
>+#endif
>+
>+#include <vlc_common.h>
>+
>+#include "libvlc.h"
>+
>+#include <assert.h>
>+#include <windows.h>
>+#include <objbase.h>
>+
>+typedef struct vlc_mta_holder
>+{
>+    VLC_COMMON_MEMBERS
>+
>+    vlc_thread_t thread;
>+    vlc_cond_t   cond;
>+    vlc_mutex_t  lock;
>+    bool         b_done;
>+} vlc_mta_holder;
>+
>+static vlc_mta_holder* sp_mta = NULL;
>+static vlc_mutex_t s_mutex = VLC_STATIC_MUTEX;
>+
>+static void* MtaMainLoop( void* opaque )
>+{
>+    vlc_mta_holder* p_mta = (vlc_mta_holder*)opaque;
>+    msg_Dbg( p_mta, "Acquiring MTA from a background thread" );
>+    CoInitializeEx( NULL, COINIT_MULTITHREADED );
>+    vlc_mutex_lock( &p_mta->lock );
>+    while( p_mta->b_done == false )
>+    {
>+        vlc_cond_wait( &p_mta->cond, &p_mta->lock );
>+    }
>+    vlc_mutex_unlock( &p_mta->lock );
>+    msg_Dbg( p_mta, "Releasing background MTA" );
>+    CoUninitialize();
>+    return NULL;
>+}
>+
>+static void MtaDestructor( vlc_object_t* p_obj )
>+{
>+    sp_mta = NULL;
>+
>+    vlc_mta_holder* p_mta = (vlc_mta_holder*)p_obj;
>+
>+    vlc_mutex_lock( &p_mta->lock );
>+    p_mta->b_done = true;
>+    vlc_cond_signal( &p_mta->cond );
>+    vlc_mutex_unlock( &p_mta->lock );
>+
>+    vlc_join( p_mta->thread, NULL );
>+}
>+
>+vlc_mta_holder* vlc_mta_acquire( vlc_object_t* p_obj )
>+{
>+    assert( p_obj != NULL );
>+    vlc_mutex_lock( &s_mutex );
>+    if ( sp_mta == NULL )
>+    {
>+        sp_mta = vlc_object_create( p_obj->obj.libvlc, sizeof( *sp_mta
>) );
>+        if ( unlikely( sp_mta == NULL ) )
>+        {
>+            vlc_mutex_unlock( &s_mutex );
>+            return NULL;
>+        }
>+        vlc_cond_init( &sp_mta->cond );
>+        vlc_mutex_init( &sp_mta->lock );
>+        vlc_object_set_destructor( sp_mta, MtaDestructor );
>+        sp_mta->b_done = false;
>+        if ( vlc_clone( &sp_mta->thread, MtaMainLoop, sp_mta,
>VLC_THREAD_PRIORITY_LOW ) )
>+        {
>+            vlc_mutex_destroy( &sp_mta->lock );
>+            vlc_cond_destroy( &sp_mta->cond );
>+            vlc_object_release( sp_mta );
>+            sp_mta = NULL;
>+        }
>+    }
>+    else
>+        vlc_object_hold( sp_mta );
>+    vlc_mutex_unlock( &s_mutex );
>+    return sp_mta;
>+}
>+
>+void vlc_mta_release( vlc_mta_holder* p_mta )
>+{
>+    assert( p_mta != NULL );
>+    vlc_mutex_lock( &s_mutex );
>+    vlc_object_release( VLC_OBJECT( p_mta ) );
>+    vlc_mutex_unlock( &s_mutex );
>+}
>-- 
>2.11.0
>
>_______________________________________________
>vlc-devel mailing list
>To unsubscribe or modify your subscription options:
>https://mailman.videolan.org/listinfo/vlc-devel

This won't work if:
- LibVLC instance A creates the object.
- LibVLC instance B yields the object.
- A releases the object.
- A is terminated.
So you can't use a VLC object here.

Also would be a lot simpler with a semaphore.
-- 
Rémi Denis-Courmont


More information about the vlc-devel mailing list