glshader: properly unref the stages on failure
authorMatthew Waters <matthew@centricular.com>
Wed, 11 Nov 2015 01:23:30 +0000 (12:23 +1100)
committerMatthew Waters <matthew@centricular.com>
Wed, 11 Nov 2015 03:41:38 +0000 (14:41 +1100)
When failing in the varargs functions, all the stage objects not handled need to
be unreffed to prevent a leak.

gst-libs/gst/gl/gstglshader.c
gst-libs/gst/gl/gstglutils.c

index cbd300d..218c0a8 100644 (file)
@@ -197,6 +197,7 @@ _new_with_stages_va_list (GstGLContext * context, GError ** error,
 {
   GstGLShader *shader;
   GstGLSLStage *stage;
+  gboolean to_unref_and_out = FALSE;
 
   g_return_val_if_fail (GST_IS_GL_CONTEXT (context), NULL);
 
@@ -204,18 +205,29 @@ _new_with_stages_va_list (GstGLContext * context, GError ** error,
   shader->context = gst_object_ref (context);
 
   while ((stage = va_arg (varargs, GstGLSLStage *))) {
+    if (to_unref_and_out) {
+      gst_object_unref (stage);
+      continue;
+    }
+
     if (!gst_glsl_stage_compile (stage, error)) {
-      gst_object_unref (shader);
-      return NULL;
+      gst_object_unref (stage);
+      to_unref_and_out = TRUE;
+      continue;
     }
     if (!gst_gl_shader_attach (shader, stage)) {
       g_set_error (error, GST_GLSL_ERROR, GST_GLSL_ERROR_PROGRAM,
           "Failed to attach stage to program");
-      gst_object_unref (shader);
-      return NULL;
+      to_unref_and_out = TRUE;
+      continue;
     }
   }
 
+  if (to_unref_and_out) {
+    gst_object_unref (shader);
+    return NULL;
+  }
+
   return shader;
 }
 
index d80aaab..ae48d7c 100644 (file)
@@ -397,6 +397,7 @@ _compile_shader (GstGLContext * context, struct _compile_shader *data)
         GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, data->vertex_src);
     if (!gst_glsl_stage_compile (vert, &error)) {
       GST_ERROR_OBJECT (vert, "%s", error->message);
+      gst_object_unref (vert);
       gst_object_unref (shader);
       return;
     }
@@ -413,6 +414,7 @@ _compile_shader (GstGLContext * context, struct _compile_shader *data)
         data->fragment_src);
     if (!gst_glsl_stage_compile (frag, &error)) {
       GST_ERROR_OBJECT (frag, "%s", error->message);
+      gst_object_unref (frag);
       gst_object_unref (shader);
       return;
     }