[vlc-commits] upnp: fix deadlock when calling UpnpFinish locked
Thomas Guillem
git at videolan.org
Mon Feb 8 16:02:56 CET 2016
vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Wed Feb 3 13:19:44 2016 +0100| [7e11257c2823417b582f4e4ad3108dce7c4c372e] | committer: Thomas Guillem
upnp: fix deadlock when calling UpnpFinish locked
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=7e11257c2823417b582f4e4ad3108dce7c4c372e
---
modules/services_discovery/upnp.cpp | 16 +++++++++++++++-
modules/services_discovery/upnp.hpp | 1 +
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/modules/services_discovery/upnp.cpp b/modules/services_discovery/upnp.cpp
index f7bfb4f..99988dd 100644
--- a/modules/services_discovery/upnp.cpp
+++ b/modules/services_discovery/upnp.cpp
@@ -73,6 +73,7 @@ struct access_sys_t
UpnpInstanceWrapper* UpnpInstanceWrapper::s_instance;
vlc_mutex_t UpnpInstanceWrapper::s_lock = VLC_STATIC_MUTEX;
+vlc_cond_t UpnpInstanceWrapper::s_cond = VLC_STATIC_COND;
/*
* VLC callback prototypes
@@ -1060,6 +1061,12 @@ UpnpInstanceWrapper::~UpnpInstanceWrapper()
UpnpInstanceWrapper *UpnpInstanceWrapper::get(vlc_object_t *p_obj, Upnp_FunPtr callback, SD::MediaServerList *opaque)
{
vlc_mutex_locker lock( &s_lock );
+
+ /* refcount is 0 but instance is not NULL, UpnpFinish is being called so
+ * wait for it to finish */
+ while ( s_instance != NULL && s_instance->refcount_ == 0 )
+ vlc_cond_wait( &s_cond, &s_lock );
+
if ( s_instance == NULL )
{
UpnpInstanceWrapper* instance = new(std::nothrow) UpnpInstanceWrapper;
@@ -1118,7 +1125,7 @@ UpnpInstanceWrapper *UpnpInstanceWrapper::get(vlc_object_t *p_obj, Upnp_FunPtr c
void UpnpInstanceWrapper::release(bool isSd)
{
- vlc_mutex_locker lock( &s_lock );
+ vlc_mutex_lock( &s_lock );
if ( isSd )
{
callback_ = NULL;
@@ -1126,9 +1133,16 @@ void UpnpInstanceWrapper::release(bool isSd)
}
if (--s_instance->refcount_ == 0)
{
+ vlc_mutex_unlock( &s_lock );
+ /* UpnpFinish must be called unlocked since callbacks can still be
+ * called when shuting down upnp threads */
delete s_instance;
+ vlc_mutex_lock( &s_lock );
+
s_instance = NULL;
+ vlc_cond_signal( &s_cond );
}
+ vlc_mutex_unlock( &s_lock );
}
UpnpClient_Handle UpnpInstanceWrapper::handle() const
diff --git a/modules/services_discovery/upnp.hpp b/modules/services_discovery/upnp.hpp
index 0cdbd8d..a6d720f 100644
--- a/modules/services_discovery/upnp.hpp
+++ b/modules/services_discovery/upnp.hpp
@@ -71,6 +71,7 @@ private:
private:
static UpnpInstanceWrapper* s_instance;
static vlc_mutex_t s_lock;
+ static vlc_cond_t s_cond;
UpnpClient_Handle handle_;
SD::MediaServerList* opaque_;
Upnp_FunPtr callback_;
More information about the vlc-commits
mailing list