[vlc-commits] [Git][videolan/vlc][master] 2 commits: macosx: VLCMain: use CFRunLoop to avoid servicing dispatch

Steve Lhomme (@robUx4) gitlab at videolan.org
Thu Oct 3 12:17:47 UTC 2024



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
feefb1d7 by Alexandre Janniaux at 2024-10-03T11:36:23+00:00
macosx: VLCMain: use CFRunLoop to avoid servicing dispatch

The main dispatch_queue is a serial queue and cannot be re-entered, so
we cannot start the NSApp runloop there since it will block into the
callback while servicing the main queue, and thus no more blocks will
be able to be executed on this main dispatch_queue. It is visible with
the callstack there:

      thread #1, queue = 'com.apple.main-thread'
        frame #0: 0x0000000183c3e1f4 libsystem_kernel.dylib`mach_msg2_trap + 8
        frame #1: 0x0000000183c50b24 libsystem_kernel.dylib`mach_msg2_internal + 80
        frame #2: 0x0000000183c46e34 libsystem_kernel.dylib`mach_msg_overwrite + 476
        frame #3: 0x0000000183c3e578 libsystem_kernel.dylib`mach_msg + 24
        frame #4: 0x0000000183d5e680 CoreFoundation`__CFRunLoopServiceMachPort + 160
        frame #5: 0x0000000183d5cf44 CoreFoundation`__CFRunLoopRun + 1208
        frame #6: 0x0000000183d5c434 CoreFoundation`CFRunLoopRunSpecific + 608
        frame #7: 0x000000018e50019c HIToolbox`RunCurrentEventLoopInMode + 292
        frame #8: 0x000000018e4fffd8 HIToolbox`ReceiveNextEventCommon + 648
        frame #9: 0x000000018e4ffd30 HIToolbox`_BlockUntilNextEventMatchingListInModeWithFilter + 76
        frame #10: 0x00000001875bbd68 AppKit`_DPSNextEvent + 660
        frame #11: 0x0000000187db1808 AppKit`-[NSApplication(NSEventRouting) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 700
        frame #12: 0x00000001875af09c AppKit`-[NSApplication run] + 476
        frame #13: 0x00000001030b791c libmacosx_plugin.dylib`__OpenIntf_block_invoke_2(.block_descriptor=<unavailable>) at VLCMain.m:166:17 [opt]
        frame #14: 0x0000000183acc750 libdispatch.dylib`_dispatch_call_block_and_release + 32
        frame #15: 0x0000000183ace3e8 libdispatch.dylib`_dispatch_client_callout + 20
        frame #16: 0x0000000183adcbb8 libdispatch.dylib`_dispatch_main_queue_drain + 988
        frame #17: 0x0000000183adc7cc libdispatch.dylib`_dispatch_main_queue_callback_4CF + 44
        frame #18: 0x0000000183d9fad4 CoreFoundation`__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 16
        frame #19: 0x0000000183d5d258 CoreFoundation`__CFRunLoopRun + 1996
        frame #20: 0x0000000183d5c434 CoreFoundation`CFRunLoopRunSpecific + 608
        frame #21: 0x0000000183dda45c CoreFoundation`CFRunLoopRun + 64
        frame #22: 0x0000000100003084 vlc-osx-static`main(i_argc=1, ppsz_argv=0x000000016fdff0c8) at darwinvlc.m:309:9 [opt]
        frame #23: 0x00000001838f60e0 dyld`start + 2360

By running the CFRunLoop instead, we don't have this serial execution
constraint and can re-enter the loop while servicing the main dispatch
queue from inside the [NSApp run] runloop. It now has the following
callstack when running:

     thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
        frame #0: 0x0000000183c3e1f4 libsystem_kernel.dylib`mach_msg2_trap + 8
        frame #1: 0x0000000183c50b24 libsystem_kernel.dylib`mach_msg2_internal + 80
        frame #2: 0x0000000183c46e34 libsystem_kernel.dylib`mach_msg_overwrite + 476
        frame #3: 0x0000000183c3e578 libsystem_kernel.dylib`mach_msg + 24
        frame #4: 0x0000000183d5e680 CoreFoundation`__CFRunLoopServiceMachPort + 160
        frame #5: 0x0000000183d5cf44 CoreFoundation`__CFRunLoopRun + 1208
        frame #6: 0x0000000183d5c434 CoreFoundation`CFRunLoopRunSpecific + 608
        frame #7: 0x000000018e50019c HIToolbox`RunCurrentEventLoopInMode + 292
        frame #8: 0x000000018e4fffd8 HIToolbox`ReceiveNextEventCommon + 648
        frame #9: 0x000000018e4ffd30 HIToolbox`_BlockUntilNextEventMatchingListInModeWithFilter + 76
        frame #10: 0x00000001875bbd68 AppKit`_DPSNextEvent + 660
        frame #11: 0x0000000187db1808 AppKit`-[NSApplication(NSEventRouting) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 700
        frame #12: 0x00000001875af09c AppKit`-[NSApplication run] + 476
        frame #13: 0x00000001030b76c8 libmacosx_plugin.dylib`__OpenIntf_block_invoke(.block_descriptor=0x00006000038813c0) at VLCMain.m:166:13 [opt]
        frame #14: 0x0000000183d5e070 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 28
        frame #15: 0x0000000183d5df84 CoreFoundation`__CFRunLoopDoBlocks + 356
        frame #16: 0x0000000183d5d414 CoreFoundation`__CFRunLoopRun + 2440
        frame #17: 0x0000000183d5c434 CoreFoundation`CFRunLoopRunSpecific + 608
        frame #18: 0x0000000183dda45c CoreFoundation`CFRunLoopRun + 64
        frame #19: 0x0000000100003084 vlc-osx-static`main(i_argc=1, ppsz_argv=0x000000016fdff0c8) at darwinvlc.m:309:9 [opt]
        frame #20: 0x00000001838f60e0 dyld`start + 2360

And now dispatch will correctly work inside this.

Regression from 3a6bd45b9e8d1f4c5e24b6031a8df44523e6c4b1 which
introduced the dispatch call and then changed also in
9cae3668c7fc1fc00939f0683c0c2293556a8d39 which also modified the
dispatch call in the destructor.

Fixes #28812

- - - - -
0b2a6f48 by Alexandre Janniaux at 2024-10-03T11:36:23+00:00
qt: use CFRunLoop to avoid servicing dispatch

The main dispatch_queue is a serial queue and cannot be re-entered, so
we cannot start the QApplication there since it will block into
a callback while servicing the main queue, and thus no more blocks will
be able to be executed on this main dispatch_queue.

By running the CFRunLoop instead, we don't have this serial execution
constraint and can re-enter the loop while servicing the main dispatch
queue from inside the QApplication runloop.

Regression from 9cae3668c7fc1fc00939f0683c0c2293556a8d39 which
introduced the dispatch call.

- - - - -


2 changed files:

- modules/gui/macosx/main/VLCMain.m
- modules/gui/qt/qt.cpp


Changes:

=====================================
modules/gui/macosx/main/VLCMain.m
=====================================
@@ -142,7 +142,8 @@ intf_thread_t *getIntf()
 int OpenIntf (vlc_object_t *p_this)
 {
     __block int retcode = VLC_SUCCESS;
-    dispatch_sync(dispatch_get_main_queue(), ^{
+    __block dispatch_semaphore_t sem = dispatch_semaphore_create(0);
+    CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopDefaultMode, ^{
         @autoreleasepool {
             intf_thread_t *p_intf = (intf_thread_t*) p_this;
             p_interface_thread = p_intf;
@@ -161,11 +162,13 @@ int OpenIntf (vlc_object_t *p_this)
                 retcode = VLC_EGENERIC;
                 return;
             }
-            dispatch_async(dispatch_get_main_queue(), ^{
-                [NSApp run];
-            });
+            dispatch_semaphore_signal(sem);
+            [NSApp run];
         }
     });
+    CFRunLoopWakeUp(CFRunLoopGetMain());
+
+    dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
 
     return retcode;
 }


=====================================
modules/gui/qt/qt.cpp
=====================================
@@ -536,10 +536,9 @@ static void *Thread( void * );
 static void *ThreadCleanup( qt_intf_t *p_intf, CleanupReason cleanupReason );
 
 #ifdef Q_OS_MAC
-static void ThreadDarwin(void *);
 /* Used to abort the app.exec() on OSX after libvlc_Quit is called */
 #include "../../../lib/libvlc_internal.h" /* libvlc_SetExitHandler */
-#include <dispatch/dispatch.h>
+#include <CoreFoundation/CFRunLoop.h>
 static void Abort( void *obj )
 {
     (void)obj;
@@ -600,7 +599,10 @@ static int OpenInternal( qt_intf_t *p_intf )
 #ifdef Q_OS_MAC
     /* Run mainloop on the main thread as Cocoa requires */
     libvlc_SetExitHandler( vlc_object_instance(p_intf), Abort, p_intf );
-    dispatch_async_f(dispatch_get_main_queue(), static_cast<void*>(p_intf), ThreadDarwin);
+    CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopDefaultMode, ^{
+        Thread(static_cast<void*>(p_intf));
+    });
+    CFRunLoopWakeUp(CFRunLoopGetMain());
 #else
     if( vlc_clone( &p_intf->thread, Thread, p_intf ) )
     {
@@ -1068,13 +1070,6 @@ static void *Thread( void *obj )
     return ThreadCleanup( p_intf, CLEANUP_APP_TERMINATED );
 }
 
-#ifdef Q_OS_MAC
-static void ThreadDarwin(void *opaque)
-{
-    Thread(opaque);
-}
-#endif
-
 static void *ThreadCleanup( qt_intf_t *p_intf, CleanupReason cleanupReason )
 {
     {



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/9285760f0c260679262d3976d833b63f2d66e33e...0b2a6f48bd062d9b77164e14d731aa79abed3ae1

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/9285760f0c260679262d3976d833b63f2d66e33e...0b2a6f48bd062d9b77164e14d731aa79abed3ae1
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list