[vlmc-devel] Fix potential deadlock when parsing metadata.

Hugo Beauzée-Luyssen git at videolan.org
Mon Feb 24 20:09:44 CET 2014


vlmc | branch: master | Hugo Beauzée-Luyssen <hugo at beauzee.fr> | Mon Feb 24 19:46:20 2014 +0200| [b5f2e911189b378f885f8a007c7eec918ea7a011] | committer: Hugo Beauzée-Luyssen

Fix potential deadlock when parsing metadata.

Turns out setTime might process synchronously :(

> http://git.videolan.org/gitweb.cgi/vlmc.git/?a=commit;h=b5f2e911189b378f885f8a007c7eec918ea7a011
---

 src/Backend/VLC/EventWaiter.cpp |    8 ++++++--
 src/Backend/VLC/EventWaiter.h   |   10 +++++++---
 src/Backend/VLC/VLCSource.cpp   |    4 ++--
 3 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/src/Backend/VLC/EventWaiter.cpp b/src/Backend/VLC/EventWaiter.cpp
index 19165d9..480990a 100644
--- a/src/Backend/VLC/EventWaiter.cpp
+++ b/src/Backend/VLC/EventWaiter.cpp
@@ -24,13 +24,15 @@
 
 using namespace Backend::VLC;
 
-EventWaiter::EventWaiter( LibVLCpp::MediaPlayer* mediaPlayer )
+EventWaiter::EventWaiter( LibVLCpp::MediaPlayer* mediaPlayer, bool startLocked )
     : m_mediaPlayer( mediaPlayer )
     , m_validationCallback( NULL )
     , m_found( true )
+    , m_startLocked( startLocked )
 {
+    if ( startLocked == true )
+        m_mutex.lock();
     m_mediaPlayer->registerEvents( &EventWaiter::eventsCallback, this );
-    m_mutex.lock();
 }
 
 EventWaiter::~EventWaiter()
@@ -47,6 +49,8 @@ EventWaiter::add(libvlc_event_type_t event)
 EventWaiter::Result
 EventWaiter::wait(unsigned long timeoutMs)
 {
+    if ( m_startLocked == false )
+        m_mutex.lock();
     if ( m_waitCond.wait( &m_mutex, timeoutMs ) == false )
     {
         m_mutex.unlock();
diff --git a/src/Backend/VLC/EventWaiter.h b/src/Backend/VLC/EventWaiter.h
index bf73511..2c7ef98 100644
--- a/src/Backend/VLC/EventWaiter.h
+++ b/src/Backend/VLC/EventWaiter.h
@@ -43,10 +43,13 @@ public:
      * \li <whatever action that will lead to an asynchronous event>
      * \li we->wait(...);
      *
-     * @warning If the event comes synchronously, this will deadlock. But if
-     *          it happens synchronously, why would you need this at all?
+     * @param startLocked   Specify if the EventWaiter should immediatly lock the mutex
+     * If this is false, mutex will be locked when wait() is called. This should
+     * be set to false when the function leading to the event might process synchronously
+     * and if the event will be triggered again (for instance, time & position events)
+     *
      */
-    EventWaiter( LibVLCpp::MediaPlayer* mediaPlayer );
+    EventWaiter(LibVLCpp::MediaPlayer* mediaPlayer , bool startLocked);
     ~EventWaiter();
 
     enum    Result
@@ -71,6 +74,7 @@ private:
     QMutex                      m_mutex;
     ValidationCallback          m_validationCallback;
     bool                        m_found;
+    bool                        m_startLocked;
 };
 
 } //VLC
diff --git a/src/Backend/VLC/VLCSource.cpp b/src/Backend/VLC/VLCSource.cpp
index e56d3cc..89e2e31 100644
--- a/src/Backend/VLC/VLCSource.cpp
+++ b/src/Backend/VLC/VLCSource.cpp
@@ -70,7 +70,7 @@ VLCSource::preparse()
     VmemRenderer*           renderer = new VmemRenderer( m_backend, this, NULL );
     LibVLCpp::MediaPlayer*  mediaPlayer = renderer->mediaPlayer();
     {
-        EventWaiter ew( mediaPlayer );
+        EventWaiter ew( mediaPlayer, true );
         ew.add( libvlc_MediaPlayerLengthChanged );
         renderer->start();
         if ( ew.wait( 3000 ) != EventWaiter::Success )
@@ -120,7 +120,7 @@ VLCSource::computeSnapshot( VmemRenderer* renderer )
     Q_ASSERT( m_snapshot == NULL );
     LibVLCpp::MediaPlayer*  mediaPlayer = renderer->mediaPlayer();
     {
-        EventWaiter ew( mediaPlayer );
+        EventWaiter ew( mediaPlayer, false );
         ew.add( libvlc_MediaPlayerPositionChanged );
         ew.setValidationCallback( &checkTimeChanged );
         renderer->setTime( m_length / 3 );



More information about the Vlmc-devel mailing list