[vlc-commits] upnp: correctly fix deadlock when calling UpnpUnRegisterClient

Thomas Guillem git at videolan.org
Mon Feb 8 18:20:47 CET 2016


vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Mon Feb  8 18:04:36 2016 +0100| [2d7589e4f45f97c91ef6f151dc76ef2c4810e842] | committer: Thomas Guillem

upnp: correctly fix deadlock when calling UpnpUnRegisterClient

UpnpInstanceWrapper::Callback() can be called while Upnp is unregistering via
UpnpUnRegisterClient(). Both functions locked the same mutex (s_lock) and this
resulted to a deadlock.

Add a new mutex to protect only the upnp callback.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=2d7589e4f45f97c91ef6f151dc76ef2c4810e842
---

 modules/services_discovery/upnp.cpp |    6 +++++-
 modules/services_discovery/upnp.hpp |    1 +
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/modules/services_discovery/upnp.cpp b/modules/services_discovery/upnp.cpp
index 5e7c2a1..be57054 100644
--- a/modules/services_discovery/upnp.cpp
+++ b/modules/services_discovery/upnp.cpp
@@ -1067,12 +1067,14 @@ UpnpInstanceWrapper::UpnpInstanceWrapper()
     , callback_( NULL )
     , refcount_( 0 )
 {
+    vlc_mutex_init( &callback_lock_ );
 }
 
 UpnpInstanceWrapper::~UpnpInstanceWrapper()
 {
     UpnpUnRegisterClient( handle_ );
     UpnpFinish();
+    vlc_mutex_destroy( &callback_lock_ );
 }
 
 UpnpInstanceWrapper *UpnpInstanceWrapper::get(vlc_object_t *p_obj, Upnp_FunPtr callback, SD::MediaServerList *opaque)
@@ -1127,6 +1129,7 @@ UpnpInstanceWrapper *UpnpInstanceWrapper::get(vlc_object_t *p_obj, Upnp_FunPtr c
     // This assumes a single UPNP SD instance
     if (callback && opaque)
     {
+        vlc_mutex_locker lock( &s_instance->callback_lock_ );
         assert(!s_instance->callback_ && !s_instance->opaque_);
         s_instance->opaque_ = opaque;
         s_instance->callback_ = callback;
@@ -1139,6 +1142,7 @@ void UpnpInstanceWrapper::release(bool isSd)
     vlc_mutex_locker lock( &s_lock );
     if ( isSd )
     {
+        vlc_mutex_locker lock( &callback_lock_ );
         callback_ = NULL;
         opaque_ = NULL;
     }
@@ -1157,7 +1161,7 @@ UpnpClient_Handle UpnpInstanceWrapper::handle() const
 int UpnpInstanceWrapper::Callback(Upnp_EventType event_type, void *p_event, void *p_user_data)
 {
     UpnpInstanceWrapper* self = static_cast<UpnpInstanceWrapper*>( p_user_data );
-    vlc_mutex_locker lock( &self->s_lock );
+    vlc_mutex_locker lock( &self->callback_lock_ );
     if ( !self->callback_ )
         return 0;
     self->callback_( event_type, p_event, self->opaque_ );
diff --git a/modules/services_discovery/upnp.hpp b/modules/services_discovery/upnp.hpp
index 0cdbd8d..27c7338 100644
--- a/modules/services_discovery/upnp.hpp
+++ b/modules/services_discovery/upnp.hpp
@@ -72,6 +72,7 @@ private:
     static UpnpInstanceWrapper* s_instance;
     static vlc_mutex_t s_lock;
     UpnpClient_Handle handle_;
+    vlc_mutex_t callback_lock_; // protect opaque_ and callback_
     SD::MediaServerList* opaque_;
     Upnp_FunPtr callback_;
     int refcount_;



More information about the vlc-commits mailing list