From 36a2529f8ae07fabda5a88b867307dde806a52f6 Mon Sep 17 00:00:00 2001 From: Robin Haberkorn Date: Mon, 10 Jun 2013 14:22:02 +0200 Subject: gtk-vlc-player widget: fixed VLC callback processing (dead locks) either libVLC 2.0.5 changed the semantics of their callbacks (they can be invoked from the main thread, i.e. from the VLC method resulting in the event); or GTK+ 2.24 silently changed the type of the GDK mutex from recursive to simple. in either case to avoid GDK mutex deadlocks we must check whether the VLC callback's thread already holds the lock or owns the main context --- lib/gtk-vlc-player/gtk-vlc-player.c | 44 ++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/lib/gtk-vlc-player/gtk-vlc-player.c b/lib/gtk-vlc-player/gtk-vlc-player.c index 03179ed..97a7115 100644 --- a/lib/gtk-vlc-player/gtk-vlc-player.c +++ b/lib/gtk-vlc-player/gtk-vlc-player.c @@ -38,6 +38,7 @@ #include #include +#include #ifdef G_OS_WIN32 #include #else @@ -57,6 +58,9 @@ static void gtk_vlc_player_init(GtkVlcPlayer *klass); static void gtk_vlc_player_dispose(GObject *gobject); static void gtk_vlc_player_finalize(GObject *gobject); +static inline void maybe_lock_gdk(void); +static inline void maybe_unlock_gdk(void); + #ifdef G_OS_WIN32 static BOOL CALLBACK enumerate_vlc_windows_cb(HWND hWndvlc, LPARAM lParam); static gboolean poll_vlc_event_window_cb(gpointer data); @@ -308,6 +312,34 @@ gtk_vlc_player_finalize(GObject *gobject) G_OBJECT_CLASS(gtk_vlc_player_parent_class)->finalize(gobject); } +/** + * @brief Locks GDK mutex if necessary. + * + * When GTK+ functions are invoked from another than the main + * thread (the one with the \e gtk_main() event loop), + * \e gdk_threads_enter() must be called. + * This auxiliary function is for callers (like VLC callbacks) that + * may or may not be invoked from the main event loop to avoid dead locks. + */ +static inline void +maybe_lock_gdk(void) +{ + if (!g_main_context_is_owner(g_main_context_default())) + gdk_threads_enter(); +} + +/** + * @brief Unlocks GDK mutex if necessary. + * + * @see maybe_lock_gdk + */ +static inline void +maybe_unlock_gdk(void) +{ + if (!g_main_context_is_owner(g_main_context_default())) + gdk_threads_leave(); +} + #ifdef G_OS_WIN32 static BOOL CALLBACK @@ -478,11 +510,11 @@ vlc_time_changed(const struct libvlc_event_t *event, void *user_data) { assert(event->type == libvlc_MediaPlayerTimeChanged); - /* VLC callbacks are invoked from another thread! */ - gdk_threads_enter(); + /* VLC callbacks may be invoked from another thread! */ + maybe_lock_gdk(); update_time(GTK_VLC_PLAYER(user_data), (gint64)event->u.media_player_time_changed.new_time); - gdk_threads_leave(); + maybe_unlock_gdk(); } static void @@ -490,11 +522,11 @@ vlc_length_changed(const struct libvlc_event_t *event, void *user_data) { assert(event->type == libvlc_MediaPlayerLengthChanged); - /* VLC callbacks are invoked from another thread! */ - gdk_threads_enter(); + /* VLC callbacks may be invoked from another thread! */ + maybe_lock_gdk(); update_length(GTK_VLC_PLAYER(user_data), (gint64)event->u.media_player_length_changed.new_length); - gdk_threads_leave(); + maybe_unlock_gdk(); } static void -- cgit v1.2.3