[vlc-devel] [PATCH v5 3/7] upnp: Split s_lock into two locks to solve deadlock issue
Steve Lhomme
robux4 at ycbcr.xyz
Mon Nov 25 10:03:56 CET 2019
👇🏼
On 2019-11-24 23:33, Johan Gunnarsson wrote:
> If libupnp executes a callback while vlc runs UpnpInstanceWrapper dtor, vlc will
> deadlock. This happens because the callback handler and UpnpInstanceWrapper dtor
> both takes s_lock, and Upnp_Finish waits for all callbacks to finish.
> UpnpUnRegisterRootDevice casues libupnp to broadcast "byebye" advertisements,
"causes"
> which libupnp picks up again and delivers as callbacks.
>
> This patch separates the locks into one that protects the UpnpInstanceWrapper
> refcounts and one that protects the list of listeners.
> ---
> modules/services_discovery/upnp-wrapper.cpp | 17 +++++++++--------
> modules/services_discovery/upnp-wrapper.hpp | 3 ++-
> 2 files changed, 11 insertions(+), 9 deletions(-)
>
> diff --git a/modules/services_discovery/upnp-wrapper.cpp b/modules/services_discovery/upnp-wrapper.cpp
> index 2e59061437..b3ea9b6716 100644
> --- a/modules/services_discovery/upnp-wrapper.cpp
> +++ b/modules/services_discovery/upnp-wrapper.cpp
> @@ -79,7 +79,8 @@ static const char *mediarenderer_desc =
>
> UpnpInstanceWrapper* UpnpInstanceWrapper::s_instance;
> UpnpInstanceWrapper::Listeners UpnpInstanceWrapper::s_listeners;
> -vlc_mutex_t UpnpInstanceWrapper::s_lock = VLC_STATIC_MUTEX;
> +vlc_mutex_t UpnpInstanceWrapper::s_lock_refcount = VLC_STATIC_MUTEX;
s_lock_instance might be a better name.
> +vlc_mutex_t UpnpInstanceWrapper::s_lock_listeners = VLC_STATIC_MUTEX;
>
> UpnpInstanceWrapper::UpnpInstanceWrapper()
> : m_client_handle( -1 )
> @@ -100,7 +101,7 @@ UpnpInstanceWrapper::~UpnpInstanceWrapper()
>
> UpnpInstanceWrapper *UpnpInstanceWrapper::get(vlc_object_t *p_obj)
> {
> - vlc_mutex_locker lock( &s_lock );
> + vlc_mutex_locker lock( &s_lock_refcount );
> if ( s_instance == NULL )
> {
> UpnpInstanceWrapper* instance = new(std::nothrow) UpnpInstanceWrapper;
> @@ -168,7 +169,7 @@ UpnpInstanceWrapper *UpnpInstanceWrapper::get(vlc_object_t *p_obj)
> void UpnpInstanceWrapper::release()
> {
> UpnpInstanceWrapper *p_delete = NULL;
> - vlc::threads::mutex_locker lock( &s_lock );
> + vlc::threads::mutex_locker lock( &s_lock_refcount );
> if (--s_instance->m_refcount == 0)
> {
> p_delete = s_instance;
> @@ -189,7 +190,7 @@ UpnpDevice_Handle UpnpInstanceWrapper::device_handle() const
>
> int UpnpInstanceWrapper::Callback(Upnp_EventType event_type, UpnpEventPtr p_event, void *p_user_data)
> {
> - vlc::threads::mutex_locker lock( &s_lock );
> + vlc::threads::mutex_locker lock( &s_lock_listeners );
> for (Listeners::iterator iter = s_listeners.begin(); iter != s_listeners.end(); ++iter)
> {
> (*iter)->onEvent(event_type, p_event, p_user_data);
> @@ -200,14 +201,14 @@ int UpnpInstanceWrapper::Callback(Upnp_EventType event_type, UpnpEventPtr p_even
>
> void UpnpInstanceWrapper::addListener(ListenerPtr listener)
> {
> - vlc::threads::mutex_locker lock( &s_lock );
> + vlc::threads::mutex_locker lock( &s_lock_listeners );
> if ( std::find( s_listeners.begin(), s_listeners.end(), listener) == s_listeners.end() )
> s_listeners.push_back( std::move(listener) );
> }
>
> void UpnpInstanceWrapper::removeListener(ListenerPtr listener)
> {
> - vlc::threads::mutex_locker lock( &s_lock );
> + vlc::threads::mutex_locker lock( &s_lock_listeners );
> Listeners::iterator iter = std::find( s_listeners.begin(), s_listeners.end(), listener );
> if ( iter != s_listeners.end() )
> s_listeners.erase( iter );
> @@ -215,7 +216,7 @@ void UpnpInstanceWrapper::removeListener(ListenerPtr listener)
>
> void UpnpInstanceWrapper::startMediaRenderer( vlc_object_t *p_obj )
> {
> - vlc::threads::mutex_locker lock( &s_lock );
> + vlc::threads::mutex_locker lock( &s_lock_refcount );
> if( m_mediarenderer_refcount == 0 )
> {
> int i_res;
> @@ -241,7 +242,7 @@ void UpnpInstanceWrapper::startMediaRenderer( vlc_object_t *p_obj )
>
> void UpnpInstanceWrapper::stopMediaRenderer( vlc_object_t *p_obj )
> {
> - vlc::threads::mutex_locker lock( &s_lock );
> + vlc::threads::mutex_locker lock( &s_lock_refcount );
> m_mediarenderer_refcount--;
> if( m_mediarenderer_refcount == 0 )
> {
> diff --git a/modules/services_discovery/upnp-wrapper.hpp b/modules/services_discovery/upnp-wrapper.hpp
> index 665edbf9ac..59fd1f0f5f 100644
> --- a/modules/services_discovery/upnp-wrapper.hpp
> +++ b/modules/services_discovery/upnp-wrapper.hpp
> @@ -71,7 +71,8 @@ public:
>
> private:
> static UpnpInstanceWrapper* s_instance;
> - static vlc_mutex_t s_lock;
> + static vlc_mutex_t s_lock_listeners;
> + static vlc_mutex_t s_lock_refcount;
> UpnpClient_Handle m_client_handle;
> UpnpDevice_Handle m_device_handle;
> int m_refcount;
> --
> 2.17.1
>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
>
More information about the vlc-devel
mailing list