[vlc-commits] commit: Qt4: do not crash if the video window is released after the interface ( Rémi Denis-Courmont )

2010-11-21 Thread git
vlc | branch: master | Rémi Denis-Courmont r...@remlab.net | Sun Nov 21 
13:45:19 2010 +0200| [841eb240885cbea14245dfd832c9f1ab31d12bf4] | committer: 
Rémi Denis-Courmont 

Qt4: do not crash if the video window is released after the interface

This should fix #3359.

 http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=841eb240885cbea14245dfd832c9f1ab31d12bf4
---

 modules/gui/qt4/main_interface.cpp |   10 --
 modules/gui/qt4/qt4.cpp|   66 +++
 2 files changed, 50 insertions(+), 26 deletions(-)

diff --git a/modules/gui/qt4/main_interface.cpp 
b/modules/gui/qt4/main_interface.cpp
index 5554aca..ddf568d 100644
--- a/modules/gui/qt4/main_interface.cpp
+++ b/modules/gui/qt4/main_interface.cpp
@@ -267,7 +267,8 @@ MainInterface::~MainInterface()
 if( stackCentralOldWidget == videoWidget )
 showTab( bgWidget );
 
-releaseVideoSlot();
+if( videoWidget )
+releaseVideoSlot();
 
 #ifdef WIN32
 if( himl )
@@ -601,8 +602,11 @@ void MainInterface::releaseVideo( void )
 /* Function that is CONNECTED to the previous emit */
 void MainInterface::releaseVideoSlot( void )
 {
-if( videoWidget )
-videoWidget-release();
+/* This function is called when the embedded video window is destroyed,
+ * or in the rare case that the embedded window is still here but the
+ * Qt4 interface exits. */
+assert( videoWidget );
+videoWidget-release();
 setVideoOnTop( false );
 setVideoFullScreen( false );
 
diff --git a/modules/gui/qt4/qt4.cpp b/modules/gui/qt4/qt4.cpp
index 168670b..136995c 100644
--- a/modules/gui/qt4/qt4.cpp
+++ b/modules/gui/qt4/qt4.cpp
@@ -28,6 +28,7 @@
 
 #include QApplication
 #include QDate
+#include QMutex
 
 #include qt4.hpp
 
@@ -271,11 +272,9 @@ static vlc_sem_t ready;
 #ifdef Q_WS_X11
 static char *x11_display = NULL;
 #endif
-static struct
-{
-vlc_mutex_t lock;
-bool busy;
-} one = { VLC_STATIC_MUTEX, false };
+static QMutex lock;
+static bool busy = false;
+static bool active = false;
 
 /*
  * Module callbacks
@@ -321,11 +320,7 @@ static int Open( vlc_object_t *p_this, bool 
isDialogProvider )
 char *display = NULL;
 #endif
 
-bool busy;
-vlc_mutex_lock (one.lock);
-busy = one.busy;
-one.busy = true;
-vlc_mutex_unlock (one.lock);
+QMutexLocker locker (lock);
 if (busy)
 {
 msg_Err (p_this, cannot start Qt4 multiple times);
@@ -352,9 +347,6 @@ static int Open( vlc_object_t *p_this, bool 
isDialogProvider )
 {
 delete p_sys;
 free (display);
-vlc_mutex_lock (one.lock);
-one.busy = false;
-vlc_mutex_unlock (one.lock);
 return VLC_ENOMEM;
 }
 #endif
@@ -364,6 +356,7 @@ static int Open( vlc_object_t *p_this, bool 
isDialogProvider )
  * an embedded video window. */
 vlc_sem_wait (ready);
 vlc_sem_destroy (ready);
+busy = active = true;
 
 #ifndef Q_WS_MAC
 if( !isDialogProvider )
@@ -416,8 +409,9 @@ static void Close( vlc_object_t *p_this )
 #endif
 delete p_sys;
 
-vlc_mutex_locker locker (one.lock);
-one.busy = false;
+QMutexLocker locker (lock);
+assert (busy);
+busy = false;
 }
 
 static void *Thread( void *obj )
@@ -487,15 +481,17 @@ static void *Thread( void *obj )
 
 /* Create the normal interface in non-DP mode */
 if( !p_intf-p_sys-b_isDialogProvider )
+{
 p_mi = new MainInterface( p_intf );
+p_intf-p_sys-p_mi = p_mi;
+}
 else
 p_mi = NULL;
-p_intf-p_sys-p_mi = p_mi;
 
 /* Explain how to show a dialog :D */
 p_intf-pf_show_dialog = ShowDialog;
 
-/* */
+/* Tell the main LibVLC thread we are ready */
 vlc_sem_post (ready);
 
 #ifdef Q_WS_MAC
@@ -525,9 +521,8 @@ static void *Thread( void *obj )
 msg_Dbg( p_intf, QApp exec() finished );
 if (p_mi != NULL)
 {
-#warning BUG!
-/* FIXME: the video window may still be registerd at this point */
-/* See LP#448082 as an example. */
+QMutexLocker locker (lock);
+active = false;
 
 p_intf-p_sys-p_mi = NULL;
 /* Destroy first the main interface because it is connected to some
@@ -602,6 +597,10 @@ static int WindowOpen( vlc_object_t *p_obj )
 return VLC_EGENERIC;
 }
 
+QMutexLocker locker (lock);
+if (unlikely(!active))
+return VLC_EGENERIC;
+
 MainInterface *p_mi = p_intf-p_sys-p_mi;
 msg_Dbg( p_obj, requesting video... );
 
@@ -637,6 +636,13 @@ static int WindowOpen( vlc_object_t *p_obj )
 static int WindowControl( vout_window_t *p_wnd, int i_query, va_list args )
 {
 MainInterface *p_mi = (MainInterface *)p_wnd-sys;
+QMutexLocker locker (lock);
+
+if (unlikely(!active))
+{
+msg_Warn (p_wnd, video already released before control);
+return VLC_EGENERIC;
+}
 return p_mi-controlVideo( i_query, args );
 }
 
@@ -644,8 +650,22 

[vlc-commits] commit: Qt4: do not crash if the video window is released after the interface ( Rémi Denis-Courmont )

2010-11-21 Thread git
vlc/vlc-1.1 | branch: master | Rémi Denis-Courmont r...@remlab.net | Sun Nov 
21 14:08:14 2010 +0200| [269b9f1bc1a31d5cc7f709f3398a6686cbb7bd45] | committer: 
Rémi Denis-Courmont 

Qt4: do not crash if the video window is released after the interface

This should fix #3359.
(cherry picked from commit 841eb240885cbea14245dfd832c9f1ab31d12bf4)

Conflicts:

modules/gui/qt4/main_interface.cpp
modules/gui/qt4/qt4.cpp

 http://git.videolan.org/gitweb.cgi/vlc/vlc-1.1.git/?a=commit;h=269b9f1bc1a31d5cc7f709f3398a6686cbb7bd45
---

 modules/gui/qt4/main_interface.cpp |   11 --
 modules/gui/qt4/qt4.cpp|   68 +++-
 2 files changed, 52 insertions(+), 27 deletions(-)

diff --git a/modules/gui/qt4/main_interface.cpp 
b/modules/gui/qt4/main_interface.cpp
index 1bd3e63..a3ad197 100644
--- a/modules/gui/qt4/main_interface.cpp
+++ b/modules/gui/qt4/main_interface.cpp
@@ -264,7 +264,9 @@ MainInterface::~MainInterface()
 if( stackCentralOldWidget == videoWidget )
 showTab( bgWidget );
 
-releaseVideoSlot();
+if( videoWidget )
+releaseVideoSlot();
+
 #ifdef WIN32
 if( himl )
 ImageList_Destroy( himl );
@@ -586,8 +588,11 @@ void MainInterface::releaseVideo( void )
 /* Function that is CONNECTED to the previous emit */
 void MainInterface::releaseVideoSlot( void )
 {
-if( videoWidget )
-videoWidget-release();
+/* This function is called when the embedded video window is destroyed,
+ * or in the rare case that the embedded window is still here but the
+ * Qt4 interface exits. */
+assert( videoWidget );
+videoWidget-release();
 setVideoOnTop( false );
 setVideoFullScreen( false );
 
diff --git a/modules/gui/qt4/qt4.cpp b/modules/gui/qt4/qt4.cpp
index 5ed7682..98d8aa6 100644
--- a/modules/gui/qt4/qt4.cpp
+++ b/modules/gui/qt4/qt4.cpp
@@ -28,6 +28,7 @@
 
 #include QApplication
 #include QDate
+#include QMutex
 
 #include qt4.hpp
 
@@ -267,11 +268,9 @@ static vlc_sem_t ready;
 #ifdef Q_WS_X11
 static char *x11_display = NULL;
 #endif
-static struct
-{
-vlc_mutex_t lock;
-bool busy;
-} one = { VLC_STATIC_MUTEX, false };
+static QMutex lock;
+static bool busy = false;
+static bool active = false;
 
 /*
  * Module callbacks
@@ -299,11 +298,7 @@ static int Open( vlc_object_t *p_this, bool 
isDialogProvider )
 char *display = NULL;
 #endif
 
-bool busy;
-vlc_mutex_lock (one.lock);
-busy = one.busy;
-one.busy = true;
-vlc_mutex_unlock (one.lock);
+QMutexLocker locker (lock);
 if (busy)
 {
 msg_Err (p_this, cannot start Qt4 multiple times);
@@ -326,15 +321,13 @@ static int Open( vlc_object_t *p_this, bool 
isDialogProvider )
 {
 delete p_sys;
 free (display);
-vlc_mutex_lock (one.lock);
-one.busy = false;
-vlc_mutex_unlock (one.lock);
 return VLC_ENOMEM;
 }
 
 /* */
 vlc_sem_wait (ready);
 vlc_sem_destroy (ready);
+busy = active = true;
 
 if( !p_sys-b_isDialogProvider )
 {
@@ -379,9 +372,10 @@ static void Close( vlc_object_t *p_this )
 x11_display = NULL;
 #endif
 delete p_sys;
-vlc_mutex_lock (one.lock);
-one.busy = false;
-vlc_mutex_unlock (one.lock);
+
+QMutexLocker locker (lock);
+assert (busy);
+busy = false;
 }
 
 static void *Thread( void *obj )
@@ -449,15 +443,17 @@ static void *Thread( void *obj )
 
 /* Create the normal interface in non-DP mode */
 if( !p_intf-p_sys-b_isDialogProvider )
+{
 p_mi = new MainInterface( p_intf );
+p_intf-p_sys-p_mi = p_mi;
+}
 else
 p_mi = NULL;
-p_intf-p_sys-p_mi = p_mi;
 
 /* Explain how to show a dialog :D */
 p_intf-pf_show_dialog = ShowDialog;
 
-/* */
+/* Tell the main LibVLC thread we are ready */
 vlc_sem_post (ready);
 
 /* Last settings */
@@ -478,9 +474,8 @@ static void *Thread( void *obj )
 msg_Dbg( p_intf, Exec finished() );
 if (p_mi != NULL)
 {
-#warning BUG!
-/* FIXME: the video window may still be registerd at this point */
-/* See LP#448082 as an example. */
+QMutexLocker locker (lock);
+active = false;
 
 p_intf-p_sys-p_mi = NULL;
 /* Destroy first the main interface because it is connected to some
@@ -555,6 +550,10 @@ static int WindowOpen( vlc_object_t *p_obj )
 return VLC_EGENERIC;
 }
 
+QMutexLocker locker (lock);
+if (unlikely(!active))
+return VLC_EGENERIC;
+
 MainInterface *p_mi = p_intf-p_sys-p_mi;
 msg_Dbg( p_obj, requesting video... );
 
@@ -585,6 +584,13 @@ static int WindowOpen( vlc_object_t *p_obj )
 static int WindowControl( vout_window_t *p_wnd, int i_query, va_list args )
 {
 MainInterface *p_mi = (MainInterface *)p_wnd-sys;
+QMutexLocker locker (lock);
+
+if (unlikely(!active))
+{
+msg_Warn (p_wnd,