Skip to content

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 3a6bd45b which introduced the dispatch call and then changed also in 9cae3668 which also modified the dispatch call in the destructor.

Fixes #28812 (closed)

Sorry @claucambra, not exactly sure what happened there since I had the Qt interface playing and closing correctly, which was not possible before the regression-MR (deadlock+crash), but seems to not have been possible because of the regression-MR too (playing should not be working since it uses dispatch). On the macosx GUI side, everything was also working correctly, but maybe it came from testing from an old buildtree. 🤷

Merge request reports