gl/cocoa: keep refs over async operations
authorMatthew Waters <matthew@centricular.com>
Sat, 15 Jul 2017 15:17:04 +0000 (01:17 +1000)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 9 Dec 2017 19:32:29 +0000 (19:32 +0000)
Avoids dereferencing dead objects

What happens in the autovideosink case is that context 1 is created and
destroyed before all the async operations hae executed on the associated
window.  When the delayed operations execute, they then reference dead
objects and crash.

We fix this by keeping refs over all async operations so the object
cannot be deleted while async operations are in flight.

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

gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h
gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m
gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m

index ae7abc8..9a9bef2 100644 (file)
@@ -59,7 +59,7 @@ struct _GstGLContextCocoaPrivate
 
 gboolean gst_gl_window_cocoa_create_window (GstGLWindowCocoa *window_cocoa);
 
-void _invoke_on_main (GstGLWindowCB func, gpointer data);
+void _invoke_on_main (GstGLWindowCB func, gpointer data, GDestroyNotify notify);
 
 G_END_DECLS
 
index 9e2f1e4..b3ba59e 100644 (file)
@@ -259,7 +259,7 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api,
   context_cocoa->priv->gl_context = glContext;
 
   _invoke_on_main ((GstGLWindowCB) gst_gl_window_cocoa_create_window,
-      window_cocoa);
+      gst_object_ref (window_cocoa), (GDestroyNotify) gst_object_unref);
 
   if (!context_cocoa->priv->gl_context) {
     goto error;
index 7c01702..40d6bc2 100644 (file)
@@ -175,9 +175,16 @@ gst_gl_window_cocoa_create_window (GstGLWindowCocoa *window_cocoa)
   NSRect rect = NSMakeRect (0, y, priv->preferred_width, priv->preferred_height);
   NSRect windowRect = NSMakeRect (0, y, priv->preferred_width, priv->preferred_height);
   GstGLContext *context = gst_gl_window_get_context (window);
-  GstGLContextCocoa *context_cocoa = GST_GL_CONTEXT_COCOA (context);
-  GstGLCAOpenGLLayer *layer = [[GstGLCAOpenGLLayer alloc] initWithGstGLContext:context_cocoa];
-  GstGLNSView *glView = [[GstGLNSView alloc] initWithFrameLayer:window_cocoa rect:windowRect layer:layer];
+  GstGLContextCocoa *context_cocoa;
+  GstGLCAOpenGLLayer *layer;
+  GstGLNSView *glView;
+
+  if (!context)
+    return FALSE;
+
+  context_cocoa = GST_GL_CONTEXT_COCOA (context);
+  layer = [[GstGLCAOpenGLLayer alloc] initWithGstGLContext:context_cocoa];
+  glView = [[GstGLNSView alloc] initWithFrameLayer:window_cocoa rect:windowRect layer:layer];
 
   gst_object_unref (context);
 
@@ -296,7 +303,8 @@ gst_gl_window_cocoa_show (GstGLWindow * window)
     }
 
     if (!priv->external_view && !priv->visible)
-      _invoke_on_main ((GstGLWindowCB) _show_window, window);
+      _invoke_on_main ((GstGLWindowCB) _show_window, gst_object_ref (window),
+          (GDestroyNotify) gst_object_unref);
   }
 }
 
@@ -575,13 +583,17 @@ close_window_cb (gpointer data)
 @end
 
 void
-_invoke_on_main (GstGLWindowCB func, gpointer data)
+_invoke_on_main (GstGLWindowCB func, gpointer data, GDestroyNotify notify)
 {
   if ([NSThread isMainThread]) {
     func (data);
+    if (notify)
+      notify (data);
   } else {
     dispatch_async (dispatch_get_main_queue (), ^{
       func (data);
+      if (notify)
+        notify (data);
     });
   }
 }