[vlc-devel] [PATCH] Workaround #3958

Rafaël Carré rafael.carre at gmail.com
Sun Oct 24 16:20:44 CEST 2010


Taglib doesn't seem to be thread safe
---
 modules/meta_engine/taglib.cpp |   78 ++++++++++++++++++++++++++++++++-------
 1 files changed, 64 insertions(+), 14 deletions(-)

diff --git a/modules/meta_engine/taglib.cpp b/modules/meta_engine/taglib.cpp
index 33866d0..b1f67c2 100644
--- a/modules/meta_engine/taglib.cpp
+++ b/modules/meta_engine/taglib.cpp
@@ -82,6 +82,13 @@
 static int ReadMeta    ( vlc_object_t * );
 static int WriteMeta   ( vlc_object_t * );
 
+static struct
+{
+    bool busy;
+    vlc_mutex_t lock;
+} entrant = { false, VLC_STATIC_MUTEX, };
+
+
 vlc_module_begin ()
     set_capability( "meta reader", 1000 )
     set_callbacks( ReadMeta, NULL )
@@ -366,7 +373,8 @@ static int ReadMeta( vlc_object_t* p_this)
     demux_meta_t*   p_demux_meta = (demux_meta_t *)p_this;
     demux_t*        p_demux = p_demux_meta->p_demux;
     vlc_meta_t*     p_meta;
-    FileRef f;
+    Tag* p_tag;
+    int ret = VLC_EGENERIC;
 
     p_demux_meta->p_meta = NULL;
     if( strcmp( p_demux->psz_access, "file" ) )
@@ -376,12 +384,24 @@ static int ReadMeta( vlc_object_t* p_this)
     if( !psz_path )
         return VLC_ENOMEM;
 
+    vlc_mutex_lock( &entrant.lock );
+    if( entrant.busy )
+    {
+        msg_Err( p_demux_meta, "taglib already active" );
+        vlc_mutex_unlock( &entrant.lock );
+        return VLC_EGENERIC;
+    }
+    entrant.busy = true;
+    vlc_mutex_unlock( &entrant.lock );
+
+    FileRef f;
+
 #if defined(WIN32) || defined (UNDER_CE)
     wchar_t wpath[MAX_PATH + 1];
     if( !MultiByteToWideChar( CP_UTF8, 0, psz_path, -1, wpath, MAX_PATH) )
     {
         free( psz_path );
-        return VLC_EGENERIC;
+        goto end;
     }
     wpath[MAX_PATH] = L'\0';
     f = FileRef( wpath );
@@ -390,7 +410,7 @@ static int ReadMeta( vlc_object_t* p_this)
     if( !local_name )
     {
         free( psz_path );
-        return VLC_EGENERIC;
+        goto end;
     }
     f = FileRef( local_name );
     LocaleFree( local_name );
@@ -398,17 +418,20 @@ static int ReadMeta( vlc_object_t* p_this)
     free( psz_path );
 
     if( f.isNull() )
-        return VLC_EGENERIC;
+        goto end;
     if( !f.tag() || f.tag()->isEmpty() )
-        return VLC_EGENERIC;
+        goto end;
 
     p_demux_meta->p_meta = p_meta = vlc_meta_New();
     if( !p_meta )
-        return VLC_ENOMEM;
+    {
+        ret = VLC_ENOMEM;
+        goto end;
+    }
 
 
     // Read the tags from the file
-    Tag* p_tag = f.tag();
+    p_tag = f.tag();
 
 #define SET( tag, meta )                                                       \
     if( !p_tag->tag().isNull() && !p_tag->tag().isEmpty() )                    \
@@ -489,7 +512,14 @@ static int ReadMeta( vlc_object_t* p_this)
             ReadMetaFromAPE( wavpack->APETag(), p_demux, p_demux_meta, p_meta );
     }
 
-    return VLC_SUCCESS;
+    ret = VLC_SUCCESS;
+
+end:
+    vlc_mutex_lock( &entrant.lock );
+    entrant.busy = false;
+    vlc_mutex_unlock( &entrant.lock );
+
+    return ret;
 }
 
 
@@ -587,7 +617,8 @@ static int WriteMeta( vlc_object_t *p_this )
 {
     meta_export_t *p_export = (meta_export_t *)p_this;
     input_item_t *p_item = p_export->p_item;
-    FileRef f;
+    Tag *p_tag;
+    int ret = VLC_EGENERIC;
 
     if( !p_item )
     {
@@ -595,16 +626,28 @@ static int WriteMeta( vlc_object_t *p_this )
         return VLC_EGENERIC;
     }
 
+    vlc_mutex_lock( &entrant.lock );
+    if( entrant.busy )
+    {
+        msg_Err( p_export, "taglib already active" );
+        vlc_mutex_unlock( &entrant.lock );
+        return VLC_EGENERIC;
+    }
+    entrant.busy = true;
+    vlc_mutex_unlock( &entrant.lock );
+
+    FileRef f;
+
 #if defined(WIN32) || defined (UNDER_CE)
     wchar_t wpath[MAX_PATH + 1];
     if( !MultiByteToWideChar( CP_UTF8, 0, p_export->psz_file, -1, wpath, MAX_PATH) )
-        return VLC_EGENERIC;
+        goto end;
     wpath[MAX_PATH] = L'\0';
     f = FileRef( wpath );
 #else
     const char* local_name = ToLocale( p_export->psz_file );
     if( !local_name )
-        return VLC_EGENERIC;
+        goto end;
     f = FileRef( local_name );
     LocaleFree( local_name );
 #endif
@@ -613,12 +656,12 @@ static int WriteMeta( vlc_object_t *p_this )
     {
         msg_Err( p_this, "File %s can't be opened for tag writing",
                  p_export->psz_file );
-        return VLC_EGENERIC;
+        goto end;
     }
 
     msg_Dbg( p_this, "Writing metadata for %s", p_export->psz_file );
 
-    Tag *p_tag = f.tag();
+    p_tag = f.tag();
 
     char *psz_meta;
 
@@ -702,6 +745,13 @@ static int WriteMeta( vlc_object_t *p_this )
     // Save the meta data
     f.save();
 
-    return VLC_SUCCESS;
+    ret = VLC_SUCCESS;
+
+end:
+    vlc_mutex_lock( &entrant.lock );
+    entrant.busy = false;
+    vlc_mutex_unlock( &entrant.lock );
+
+    return ret;
 }
 
-- 
1.7.3.2





More information about the vlc-devel mailing list