macos: Fix race conditions
authorCorentin Damman <c.damman@intopix.com>
Tue, 1 Oct 2024 12:26:40 +0000 (12:26 +0000)
committerBackport Bot <gitlab-backport-bot@gstreamer-foundation.org>
Thu, 3 Oct 2024 14:21:05 +0000 (15:21 +0100)
This commit fixes two issues:
- The event must be posted *after* calling stop, otherwise a race condition can occur and the app never stops
- isFinishedLaunching and applicationDidFinishLaunching are not always synchronized, causing sometimes
  a deadlock on the g_cond_wait never catching the g_cond_signal

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

subprojects/gstreamer/gst/gstmacos.m

index dbdb1a70a396ba3b7e7d3baf246dd0fa5c7135f5..bb943ac8255f3a710a243924856958a085d44df4 100644 (file)
@@ -11,11 +11,13 @@ struct _ThreadArgs {
   gboolean is_simple;
   GMutex nsapp_mutex;
   GCond nsapp_cond;
+  gboolean nsapp_running;
 };
 
 @interface GstCocoaApplicationDelegate : NSObject <NSApplicationDelegate>
 @property (assign) GMutex *nsapp_mutex;
 @property (assign) GCond *nsapp_cond;
+@property (assign) gboolean *nsapp_running;
 @end
 
 @implementation GstCocoaApplicationDelegate
@@ -23,6 +25,7 @@ struct _ThreadArgs {
 - (void)applicationDidFinishLaunching:(NSNotification *)notification
 {
   g_mutex_lock (self.nsapp_mutex);
+  *self.nsapp_running = TRUE;
   g_cond_signal (self.nsapp_cond);
   g_mutex_unlock (self.nsapp_mutex);
 }
@@ -35,7 +38,7 @@ gst_thread_func (ThreadArgs *args)
   /* Only proceed once NSApp is running, otherwise we could
    * attempt to call [NSApp: stop] before it's even started. */
   g_mutex_lock (&args->nsapp_mutex);
-  while (![[NSRunningApplication currentApplication] isFinishedLaunching]) {
+  while (!args->nsapp_running) {
     g_cond_wait (&args->nsapp_cond, &args->nsapp_mutex);
   }
   g_mutex_unlock (&args->nsapp_mutex);
@@ -55,11 +58,11 @@ gst_thread_func (ThreadArgs *args)
                    windowNumber: 0
                         context: nil
                         subtype: NSEventSubtypeApplicationActivated
-                          data1: 0 
+                          data1: 0
                           data2: 0];
 
-  [NSApp postEvent:event atStart:YES];
   [NSApp stop:nil];
+  [NSApp postEvent:event atStart:YES];
 
   return ret;
 }
@@ -73,11 +76,13 @@ run_main_with_nsapp (ThreadArgs args)
 
   g_mutex_init (&args.nsapp_mutex);
   g_cond_init (&args.nsapp_cond);
+  args.nsapp_running = FALSE;
 
   [NSApplication sharedApplication];
   delegate = [[GstCocoaApplicationDelegate alloc] init];
   delegate.nsapp_mutex = &args.nsapp_mutex;
   delegate.nsapp_cond = &args.nsapp_cond;
+  delegate.nsapp_running = &args.nsapp_running;
   [NSApp setDelegate:delegate];
 
   /* This lets us show an icon in the dock and correctly focus opened windows */
@@ -102,11 +107,11 @@ run_main_with_nsapp (ThreadArgs args)
  * @argv: (array length=argc): an array of arguments to be passed to the main function
  * @user_data: (nullable): user data to be passed to the main function
  *
- * Starts an NSApplication on the main thread before calling 
- * the provided main() function on a secondary thread. 
- * 
- * This ensures that GStreamer can correctly perform actions 
- * such as creating a GL window, which require a Cocoa main loop 
+ * Starts an NSApplication on the main thread before calling
+ * the provided main() function on a secondary thread.
+ *
+ * This ensures that GStreamer can correctly perform actions
+ * such as creating a GL window, which require a Cocoa main loop
  * to be running on the main thread.
  *
  * Do not call this function more than once - especially while
@@ -144,7 +149,7 @@ gst_macos_main (GstMainFunc main_func, int argc, char **argv, gpointer user_data
  *
  * Since: 1.22
  */
-int 
+int
 gst_macos_main_simple (GstMainFuncSimple main_func, gpointer user_data)
 {
   ThreadArgs args;