macos: Fix race conditions

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/7593>
This commit is contained in:
Corentin Damman 2024-10-01 12:26:40 +00:00
parent aaf9b46e2f
commit 16da96653a

View 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;