glcontext: fix race between creation/shutdown
authorMatthew Waters <matthew@centricular.com>
Mon, 28 Nov 2016 03:19:18 +0000 (14:19 +1100)
committerMatthew Waters <matthew@centricular.com>
Mon, 28 Nov 2016 09:09:06 +0000 (20:09 +1100)
626bcccff96f624f59c5212b3e21e472240171fd removed some locks that
allowed the main loop quit to occur before the context was fully
created.

2776cef25d2a98668b73272aecfe77e684e6627e attempted to readd them but
missed the scop of the quit() call.

Also remove the use of g_thread_join() as that's not safe to use when
it's possible to lose the last reference from the GL thread.

https://bugzilla.gnome.org/show_bug.cgi?id=775171

gst-libs/gst/gl/gstglcontext.c

index eb46e6ccd6b326114f216328993c52cfbe2d3aac..975f7d80c6abf0092cf07e3fd35e67ee2b5bc756 100644 (file)
@@ -201,6 +201,7 @@ struct _GstGLContextPrivate
   /* conditions */
   GMutex render_lock;
   GCond create_cond;
+  GCond destroy_cond;
 
   gboolean created;
   gboolean alive;
@@ -272,6 +273,7 @@ gst_gl_context_init (GstGLContext * context)
   g_mutex_init (&context->priv->render_lock);
 
   g_cond_init (&context->priv->create_cond);
+  g_cond_init (&context->priv->destroy_cond);
   context->priv->created = FALSE;
 
   g_weak_ref_init (&context->priv->other_context_ref, NULL);
@@ -656,22 +658,20 @@ gst_gl_context_finalize (GObject * object)
     gst_gl_window_set_resize_callback (context->window, NULL, NULL, NULL);
     gst_gl_window_set_draw_callback (context->window, NULL, NULL, NULL);
 
+    g_mutex_lock (&context->priv->render_lock);
     if (context->priv->alive) {
       GST_INFO_OBJECT (context, "send quit gl window loop");
       gst_gl_window_quit (context->window);
 
       GST_INFO_OBJECT (context, "joining gl thread");
-      g_mutex_lock (&context->priv->render_lock);
-      if (context->priv->alive) {
-        GThread *t = context->priv->gl_thread;
-        g_mutex_unlock (&context->priv->render_lock);
-        g_thread_join (t);
-      } else {
-        g_mutex_unlock (&context->priv->render_lock);
-      }
+      while (context->priv->alive)
+        g_cond_wait (&context->priv->destroy_cond, &context->priv->render_lock);
       GST_INFO_OBJECT (context, "gl thread joined");
+
+      g_thread_unref (context->priv->gl_thread);
       context->priv->gl_thread = NULL;
     }
+    g_mutex_unlock (&context->priv->render_lock);
 
     gst_gl_window_set_close_callback (context->window, NULL, NULL, NULL);
     gst_object_unref (context->window);
@@ -690,6 +690,7 @@ gst_gl_context_finalize (GObject * object)
   g_mutex_clear (&context->priv->render_lock);
 
   g_cond_clear (&context->priv->create_cond);
+  g_cond_clear (&context->priv->destroy_cond);
 
   g_free (context->priv->gl_exts);
   g_weak_ref_clear (&context->priv->other_context_ref);
@@ -1290,6 +1291,7 @@ gst_gl_context_create_thread (GstGLContext * context)
   }
 
   context->priv->created = FALSE;
+  g_cond_signal (&context->priv->destroy_cond);
   g_mutex_unlock (&context->priv->render_lock);
 
   return NULL;