From 126ee924c065160738308f7a10241c63ada8bab5 Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Wed, 5 Oct 2016 18:32:09 +1100 Subject: [PATCH] glwindow: don't use g_thread_join() to join the navigation thread Using g_thread_join() in _finalize() handlers may result in a deadlock joining the current thread when the last reference is held by a signal handler. e.g.: error 'Resource deadlock avoided' during 'pthread_join (pt->system_thread, NULL)' The backtrace looks like this: [...] g_thread_join () gst_gl_window_finalize () gst_gl_window_x11_finalize () g_object_unref () g_value_unset () g_signal_emit_valist () g_signal_emit () gst_gl_window_send_mouse_event () gst_gl_window_mouse_event_cb () g_main_dispatch () [..] g_main_loop_run () gst_gl_window_navigation_thread () g_thread_proxy () start_thread () clone () --- gst-libs/gst/gl/gstglwindow.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/gst-libs/gst/gl/gstglwindow.c b/gst-libs/gst/gl/gstglwindow.c index b74d39755e..0588f1d65b 100644 --- a/gst-libs/gst/gl/gstglwindow.c +++ b/gst-libs/gst/gl/gstglwindow.c @@ -101,6 +101,7 @@ struct _GstGLWindowPrivate GMainLoop *navigation_loop; GMutex nav_lock; GCond nav_create_cond; + GCond nav_destroy_cond; gboolean nav_alive; GMutex sync_message_lock; GCond sync_message_cond; @@ -335,12 +336,16 @@ gst_gl_window_finalize (GObject * object) GstGLWindowPrivate *priv = window->priv; GST_INFO ("quit navigation loop"); + + g_mutex_lock (&window->priv->nav_lock); if (window->priv->navigation_loop) { g_main_loop_quit (window->priv->navigation_loop); /* wait until navigation thread finished */ - g_thread_join (window->priv->navigation_thread); + while (window->priv->nav_alive) + g_cond_wait (&window->priv->nav_destroy_cond, &window->priv->nav_lock); window->priv->navigation_thread = NULL; } + g_mutex_unlock (&window->priv->nav_lock); if (priv->loop) g_main_loop_unref (priv->loop); @@ -353,6 +358,7 @@ gst_gl_window_finalize (GObject * object) g_mutex_clear (&window->lock); g_mutex_clear (&window->priv->nav_lock); g_cond_clear (&window->priv->nav_create_cond); + g_cond_clear (&window->priv->nav_destroy_cond); g_mutex_clear (&window->priv->sync_message_lock); g_cond_clear (&window->priv->sync_message_cond); gst_object_unref (window->display); @@ -939,6 +945,7 @@ gst_gl_window_navigation_thread (GstGLWindow * window) g_main_loop_run (window->priv->navigation_loop); + g_mutex_lock (&window->priv->nav_lock); g_main_context_pop_thread_default (window->priv->navigation_context); g_main_loop_unref (window->priv->navigation_loop); @@ -946,6 +953,10 @@ gst_gl_window_navigation_thread (GstGLWindow * window) window->priv->navigation_loop = NULL; window->priv->navigation_context = NULL; + window->priv->nav_alive = FALSE; + g_cond_signal (&window->priv->nav_destroy_cond); + g_mutex_unlock (&window->priv->nav_lock); + GST_INFO ("navigation loop exited\n"); return NULL;