gl: Fix crash in cocoa due to race in gst_gl_context_activate()
authorNirbheek Chauhan <nirbheek@centricular.com>
Mon, 16 Jan 2023 10:25:56 +0000 (15:55 +0530)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Tue, 17 Jan 2023 21:56:41 +0000 (21:56 +0000)
We create a new context in `gst_gl_context_create_thread()` and then
activate it on the current thread. Thereafter we assume that the
current thread continues to be the active thread for that context and
call `gst_gl_context_fill_info()` which asserts that the current
thread is the active thread.

However, if at the same time a different thread calls
`send_message_async()`, it will call into
`gst_gl_window_cocoa_send_message_async()` which will schedule the
message to be invoked using GCD. That anonymous function will also
call `gst_gl_context_activate()`, which creates a race, which can lead
to:

```
gst_gl_context_fill_info: assertion 'context->priv->active_thread == g_thread_self ()' failed
```

Fix it by using `gst_gl_context_thread_add()` to invoke `fill_info()`
on the context.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3732>

subprojects/gst-plugins-base/gst-libs/gst/gl/gstglcontext.c

index 3056a4a..4eac6b2 100644 (file)
@@ -1194,8 +1194,19 @@ _build_extension_string (GstGLContext * context)
   return ext_g_str;
 }
 
-//gboolean
-//gst_gl_context_create (GstGLContext * context, GstGLContext * other_context, GError ** error)
+typedef struct
+{
+  GError **error;
+  gboolean ret;
+} FillInfoCtx;
+
+static void
+fill_info (GstGLContext * context, gpointer data)
+{
+  FillInfoCtx *ctx = data;
+  ctx->ret = gst_gl_context_fill_info (context, ctx->error);
+}
+
 static gpointer
 gst_gl_context_create_thread (GstGLContext * context)
 {
@@ -1360,9 +1371,14 @@ gst_gl_context_create_thread (GstGLContext * context)
   g_free (display_api_s);
 
   GST_DEBUG_OBJECT (context, "Filling info");
-  if (!gst_gl_context_fill_info (context, error)) {
-    g_assert (error == NULL || *error != NULL);
-    goto failure;
+  {
+    FillInfoCtx ctx = { 0 };
+    ctx.error = error;
+    gst_gl_context_thread_add (context, fill_info, &ctx);
+    if (!ctx.ret) {
+      g_assert (error == NULL || *error != NULL);
+      goto failure;
+    }
   }
 
   context->priv->alive = TRUE;