GNOME Bugzilla – Bug 703100
osxvideosink: deadlock on re-use
Last modified: 2013-07-11 16:53:36 UTC
Created attachment 247796 [details] Sources of the app that demonstrates the bug. When I'm trying to reuse osxvideosink, it often ends up with deadlock. Tested on Mac OS X 10.8.4
Created attachment 247810 [details] Another app that demonstrates the issue
Could you provide backtraces of all threads for these deadlocks with debugging symbols?
For the first sample: * thread #1: tid = 0x2203, 0x00007fff8f2280fa libsystem_kernel.dylib`__psynch_cvwait + 10, stop reason = signal SIGSTOP frame #0: 0x00007fff8f2280fa libsystem_kernel.dylib`__psynch_cvwait + 10 frame #1: 0x00007fff8d4f1fe9 libsystem_c.dylib`_pthread_cond_wait + 869 frame #2: 0x00007fff8d9e9c16 Foundation`-[NSCondition wait] + 240 frame #3: 0x00007fff8d9e23c8 Foundation`-[NSObject(NSThreadPerformAdditions) performSelector:onThread:withObject:waitUntilDone:modes:] + 796 frame #4: 0x00007fff8da1c7f9 Foundation`-[NSObject(NSThreadPerformAdditions) performSelector:onThread:withObject:waitUntilDone:] + 122 frame #5: 0x00000001005f30d5 libgstosxvideosink.so`-[GstGLView haveSuperview] + 85 frame #6: 0x00000001005f1da1 libgstosxvideosink.so`gst_osx_video_sink_change_state + 1079 frame #7: 0x000000010018fc35 libgstreamer-1.0.0.dylib`gst_element_change_state + 36 frame #8: 0x0000000100190a65 libgstreamer-1.0.0.dylib`gst_element_set_state_func + 460 frame #9: 0x0000000100177a6f libgstreamer-1.0.0.dylib`gst_bin_change_state_func + 1333 frame #10: 0x00000001001ab46d libgstreamer-1.0.0.dylib`gst_pipeline_change_state + 339 frame #11: 0x000000010018fc35 libgstreamer-1.0.0.dylib`gst_element_change_state + 36 frame #12: 0x0000000100190a65 libgstreamer-1.0.0.dylib`gst_element_set_state_func + 460 frame #13: 0x0000000100002a00 player`main(argc=1, argv=0x00007fff5fbffa08) + 1040 at main.c:73 frame #14: 0x00007fff91a7c7e1 libdyld.dylib`start + 1 thread #2: tid = 0x3103, 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #0: 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #1: 0x00007fff8d4eff4c libsystem_c.dylib`_pthread_workq_return + 25 frame #2: 0x00007fff8d4efd13 libsystem_c.dylib`_pthread_wqthread + 412 frame #3: 0x00007fff8d4da1d1 libsystem_c.dylib`start_wqthread + 13 thread #3: tid = 0x3203, 0x00007fff8f228d16 libsystem_kernel.dylib`kevent + 10 frame #0: 0x00007fff8f228d16 libsystem_kernel.dylib`kevent + 10 frame #1: 0x00007fff8a468dea libdispatch.dylib`_dispatch_mgr_invoke + 883 frame #2: 0x00007fff8a4689ee libdispatch.dylib`_dispatch_mgr_thread + 54 thread #4: tid = 0x3303, 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #0: 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #1: 0x00007fff8d4eff4c libsystem_c.dylib`_pthread_workq_return + 25 frame #2: 0x00007fff8d4efd13 libsystem_c.dylib`_pthread_wqthread + 412 frame #3: 0x00007fff8d4da1d1 libsystem_c.dylib`start_wqthread + 13 thread #5: tid = 0x3403, 0x00007fff8f226686 libsystem_kernel.dylib`mach_msg_trap + 10 frame #0: 0x00007fff8f226686 libsystem_kernel.dylib`mach_msg_trap + 10 frame #1: 0x00007fff8f225c42 libsystem_kernel.dylib`mach_msg + 70 frame #2: 0x00007fff904aa233 CoreFoundation`__CFRunLoopServiceMachPort + 195 frame #3: 0x00007fff904af916 CoreFoundation`__CFRunLoopRun + 1078 frame #4: 0x00007fff904af0e2 CoreFoundation`CFRunLoopRunSpecific + 290 frame #5: 0x00007fff917a8eb4 HIToolbox`RunCurrentEventLoopInMode + 209 frame #6: 0x00007fff917a8c52 HIToolbox`ReceiveNextEventCommon + 356 frame #7: 0x00007fff917a8ae3 HIToolbox`BlockUntilNextEventMatchingListInMode + 62 frame #8: 0x00007fff89140533 AppKit`_DPSNextEvent + 685 frame #9: 0x00007fff8913fdf2 AppKit`-[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 128 frame #10: 0x00000001005f0d2b libgstosxvideosink.so`-[GstOSXVideoSinkObject nsAppThread] + 288 frame #11: 0x00007fff8d9eb562 Foundation`__NSThread__main__ + 1345 frame #12: 0x00007fff8d4ed7a2 libsystem_c.dylib`_pthread_start + 327 frame #13: 0x00007fff8d4da1e1 libsystem_c.dylib`thread_start + 13 thread #7: tid = 0x3603, 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #0: 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #1: 0x00007fff8d4eff4c libsystem_c.dylib`_pthread_workq_return + 25 frame #2: 0x00007fff8d4efd13 libsystem_c.dylib`_pthread_wqthread + 412 frame #3: 0x00007fff8d4da1d1 libsystem_c.dylib`start_wqthread + 13 thread #8: tid = 0x3703, 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #0: 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #1: 0x00007fff8d4eff4c libsystem_c.dylib`_pthread_workq_return + 25 frame #2: 0x00007fff8d4efd13 libsystem_c.dylib`_pthread_wqthread + 412 frame #3: 0x00007fff8d4da1d1 libsystem_c.dylib`start_wqthread + 13 thread #9: tid = 0x3803, 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #0: 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #1: 0x00007fff8d4eff4c libsystem_c.dylib`_pthread_workq_return + 25 frame #2: 0x00007fff8d4efd13 libsystem_c.dylib`_pthread_wqthread + 412 frame #3: 0x00007fff8d4da1d1 libsystem_c.dylib`start_wqthread + 13 thread #10: tid = 0x3903, 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #0: 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #1: 0x00007fff8d4eff4c libsystem_c.dylib`_pthread_workq_return + 25 frame #2: 0x00007fff8d4efd13 libsystem_c.dylib`_pthread_wqthread + 412 frame #3: 0x00007fff8d4da1d1 libsystem_c.dylib`start_wqthread + 13 thread #11: tid = 0x3a03, 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #0: 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #1: 0x00007fff8d4eff4c libsystem_c.dylib`_pthread_workq_return + 25 frame #2: 0x00007fff8d4efd13 libsystem_c.dylib`_pthread_wqthread + 412 frame #3: 0x00007fff8d4da1d1 libsystem_c.dylib`start_wqthread + 13 thread #12: tid = 0x3b03, 0x00007fff8f2280fa libsystem_kernel.dylib`__psynch_cvwait + 10 frame #0: 0x00007fff8f2280fa libsystem_kernel.dylib`__psynch_cvwait + 10 frame #1: 0x00007fff8d4f1fe9 libsystem_c.dylib`_pthread_cond_wait + 869 frame #2: 0x0000000100066f82 libglib-2.0.0.dylib`g_cond_wait_until + 103 frame #3: 0x0000000100009e7e libglib-2.0.0.dylib`g_async_queue_pop_intern_unlocked + 93 frame #4: 0x0000000100009ff0 libglib-2.0.0.dylib`g_async_queue_timeout_pop + 49 frame #5: 0x000000010004f9e3 libglib-2.0.0.dylib`g_thread_pool_thread_proxy + 380 frame #6: 0x000000010004ec72 libglib-2.0.0.dylib`g_thread_proxy + 90 frame #7: 0x00007fff8d4ed7a2 libsystem_c.dylib`_pthread_start + 327 frame #8: 0x00007fff8d4da1e1 libsystem_c.dylib`thread_start + 13 thread #13: tid = 0x3c03, 0x00007fff8f226686 libsystem_kernel.dylib`mach_msg_trap + 10 frame #0: 0x00007fff8f226686 libsystem_kernel.dylib`mach_msg_trap + 10 frame #1: 0x00007fff8f225c42 libsystem_kernel.dylib`mach_msg + 70 frame #2: 0x00007fff904aa233 CoreFoundation`__CFRunLoopServiceMachPort + 195 frame #3: 0x00007fff904af916 CoreFoundation`__CFRunLoopRun + 1078 frame #4: 0x00007fff904af0e2 CoreFoundation`CFRunLoopRunSpecific + 290 frame #5: 0x00007fff917a8eb4 HIToolbox`RunCurrentEventLoopInMode + 209 frame #6: 0x00007fff917a8c52 HIToolbox`ReceiveNextEventCommon + 356 frame #7: 0x00007fff917a8ae3 HIToolbox`BlockUntilNextEventMatchingListInMode + 62 frame #8: 0x00007fff89140533 AppKit`_DPSNextEvent + 685 frame #9: 0x00007fff8913fdf2 AppKit`-[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 128 frame #10: 0x00000001005f0d2b libgstosxvideosink.so`-[GstOSXVideoSinkObject nsAppThread] + 288 frame #11: 0x00007fff8d9eb562 Foundation`__NSThread__main__ + 1345 frame #12: 0x00007fff8d4ed7a2 libsystem_c.dylib`_pthread_start + 327 frame #13: 0x00007fff8d4da1e1 libsystem_c.dylib`thread_start + 13 For the second sample: * thread #1: tid = 0x2203, 0x00007fff8f2280fa libsystem_kernel.dylib`__psynch_cvwait + 10, stop reason = signal SIGSTOP frame #0: 0x00007fff8f2280fa libsystem_kernel.dylib`__psynch_cvwait + 10 frame #1: 0x00007fff8d4f1fe9 libsystem_c.dylib`_pthread_cond_wait + 869 frame #2: 0x00007fff8d9e9c16 Foundation`-[NSCondition wait] + 240 frame #3: 0x00007fff8d9e23c8 Foundation`-[NSObject(NSThreadPerformAdditions) performSelector:onThread:withObject:waitUntilDone:modes:] + 796 frame #4: 0x00007fff8da1c7f9 Foundation`-[NSObject(NSThreadPerformAdditions) performSelector:onThread:withObject:waitUntilDone:] + 122 frame #5: 0x00000001005f30d5 libgstosxvideosink.so`-[GstGLView haveSuperview] + 85 frame #6: 0x00000001005f1da1 libgstosxvideosink.so`gst_osx_video_sink_change_state + 1079 frame #7: 0x000000010018fc35 libgstreamer-1.0.0.dylib`gst_element_change_state + 36 frame #8: 0x0000000100190a65 libgstreamer-1.0.0.dylib`gst_element_set_state_func + 460 frame #9: 0x0000000100177a6f libgstreamer-1.0.0.dylib`gst_bin_change_state_func + 1333 frame #10: 0x000000010018fc35 libgstreamer-1.0.0.dylib`gst_element_change_state + 36 frame #11: 0x0000000100190a65 libgstreamer-1.0.0.dylib`gst_element_set_state_func + 460 frame #12: 0x0000000100177a6f libgstreamer-1.0.0.dylib`gst_bin_change_state_func + 1333 frame #13: 0x00000001001ab46d libgstreamer-1.0.0.dylib`gst_pipeline_change_state + 339 frame #14: 0x000000010018fc35 libgstreamer-1.0.0.dylib`gst_element_change_state + 36 frame #15: 0x000000010018fd84 libgstreamer-1.0.0.dylib`gst_element_change_state + 371 frame #16: 0x0000000100190a65 libgstreamer-1.0.0.dylib`gst_element_set_state_func + 460 frame #17: 0x00000001000028c9 player`main(argc=1, argv=0x00007fff5fbffa08) + 585 at main.c:109 frame #18: 0x00007fff91a7c7e1 libdyld.dylib`start + 1 thread #2: tid = 0x3103, 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #0: 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #1: 0x00007fff8d4eff4c libsystem_c.dylib`_pthread_workq_return + 25 frame #2: 0x00007fff8d4efd13 libsystem_c.dylib`_pthread_wqthread + 412 frame #3: 0x00007fff8d4da1d1 libsystem_c.dylib`start_wqthread + 13 thread #3: tid = 0x3203, 0x00007fff8f228d16 libsystem_kernel.dylib`kevent + 10 frame #0: 0x00007fff8f228d16 libsystem_kernel.dylib`kevent + 10 frame #1: 0x00007fff8a468dea libdispatch.dylib`_dispatch_mgr_invoke + 883 frame #2: 0x00007fff8a4689ee libdispatch.dylib`_dispatch_mgr_thread + 54 thread #4: tid = 0x3303, 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #0: 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #1: 0x00007fff8d4eff4c libsystem_c.dylib`_pthread_workq_return + 25 frame #2: 0x00007fff8d4efd13 libsystem_c.dylib`_pthread_wqthread + 412 frame #3: 0x00007fff8d4da1d1 libsystem_c.dylib`start_wqthread + 13 thread #6: tid = 0x3503, 0x00007fff8f226686 libsystem_kernel.dylib`mach_msg_trap + 10 frame #0: 0x00007fff8f226686 libsystem_kernel.dylib`mach_msg_trap + 10 frame #1: 0x00007fff8f225c42 libsystem_kernel.dylib`mach_msg + 70 frame #2: 0x00007fff904aa233 CoreFoundation`__CFRunLoopServiceMachPort + 195 frame #3: 0x00007fff904af916 CoreFoundation`__CFRunLoopRun + 1078 frame #4: 0x00007fff904af0e2 CoreFoundation`CFRunLoopRunSpecific + 290 frame #5: 0x00007fff917a8eb4 HIToolbox`RunCurrentEventLoopInMode + 209 frame #6: 0x00007fff917a8c52 HIToolbox`ReceiveNextEventCommon + 356 frame #7: 0x00007fff917a8ae3 HIToolbox`BlockUntilNextEventMatchingListInMode + 62 frame #8: 0x00007fff89140533 AppKit`_DPSNextEvent + 685 frame #9: 0x00007fff8913fdf2 AppKit`-[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 128 frame #10: 0x00000001005f0d2b libgstosxvideosink.so`-[GstOSXVideoSinkObject nsAppThread] + 288 frame #11: 0x00007fff8d9eb562 Foundation`__NSThread__main__ + 1345 frame #12: 0x00007fff8d4ed7a2 libsystem_c.dylib`_pthread_start + 327 frame #13: 0x00007fff8d4da1e1 libsystem_c.dylib`thread_start + 13 thread #7: tid = 0x3603, 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #0: 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #1: 0x00007fff8d4eff4c libsystem_c.dylib`_pthread_workq_return + 25 frame #2: 0x00007fff8d4efd13 libsystem_c.dylib`_pthread_wqthread + 412 frame #3: 0x00007fff8d4da1d1 libsystem_c.dylib`start_wqthread + 13 thread #8: tid = 0x3703, 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #0: 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #1: 0x00007fff8d4eff4c libsystem_c.dylib`_pthread_workq_return + 25 frame #2: 0x00007fff8d4efd13 libsystem_c.dylib`_pthread_wqthread + 412 frame #3: 0x00007fff8d4da1d1 libsystem_c.dylib`start_wqthread + 13 thread #9: tid = 0x3803, 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #0: 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #1: 0x00007fff8d4eff4c libsystem_c.dylib`_pthread_workq_return + 25 frame #2: 0x00007fff8d4efd13 libsystem_c.dylib`_pthread_wqthread + 412 frame #3: 0x00007fff8d4da1d1 libsystem_c.dylib`start_wqthread + 13 thread #10: tid = 0x3903, 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #0: 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #1: 0x00007fff8d4eff4c libsystem_c.dylib`_pthread_workq_return + 25 frame #2: 0x00007fff8d4efd13 libsystem_c.dylib`_pthread_wqthread + 412 frame #3: 0x00007fff8d4da1d1 libsystem_c.dylib`start_wqthread + 13 thread #11: tid = 0x3a03, 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #0: 0x00007fff8f2286d6 libsystem_kernel.dylib`__workq_kernreturn + 10 frame #1: 0x00007fff8d4eff4c libsystem_c.dylib`_pthread_workq_return + 25 frame #2: 0x00007fff8d4efd13 libsystem_c.dylib`_pthread_wqthread + 412 frame #3: 0x00007fff8d4da1d1 libsystem_c.dylib`start_wqthread + 13 thread #12: tid = 0x3b03, 0x00007fff8f2280fa libsystem_kernel.dylib`__psynch_cvwait + 10 frame #0: 0x00007fff8f2280fa libsystem_kernel.dylib`__psynch_cvwait + 10 frame #1: 0x00007fff8d4f1fe9 libsystem_c.dylib`_pthread_cond_wait + 869 frame #2: 0x0000000100066f82 libglib-2.0.0.dylib`g_cond_wait_until + 103 frame #3: 0x0000000100009e7e libglib-2.0.0.dylib`g_async_queue_pop_intern_unlocked + 93 frame #4: 0x0000000100009ff0 libglib-2.0.0.dylib`g_async_queue_timeout_pop + 49 frame #5: 0x000000010004f9e3 libglib-2.0.0.dylib`g_thread_pool_thread_proxy + 380 frame #6: 0x000000010004ec72 libglib-2.0.0.dylib`g_thread_proxy + 90 frame #7: 0x00007fff8d4ed7a2 libsystem_c.dylib`_pthread_start + 327 frame #8: 0x00007fff8d4da1e1 libsystem_c.dylib`thread_start + 13 thread #13: tid = 0x3c03, 0x00007fff8f226686 libsystem_kernel.dylib`mach_msg_trap + 10 frame #0: 0x00007fff8f226686 libsystem_kernel.dylib`mach_msg_trap + 10 frame #1: 0x00007fff8f225c42 libsystem_kernel.dylib`mach_msg + 70 frame #2: 0x00007fff904aa233 CoreFoundation`__CFRunLoopServiceMachPort + 195 frame #3: 0x00007fff904af916 CoreFoundation`__CFRunLoopRun + 1078 frame #4: 0x00007fff904af0e2 CoreFoundation`CFRunLoopRunSpecific + 290 frame #5: 0x00007fff917a8eb4 HIToolbox`RunCurrentEventLoopInMode + 209 frame #6: 0x00007fff917a8c52 HIToolbox`ReceiveNextEventCommon + 356 frame #7: 0x00007fff917a8ae3 HIToolbox`BlockUntilNextEventMatchingListInMode + 62 frame #8: 0x00007fff89140533 AppKit`_DPSNextEvent + 685 frame #9: 0x00007fff8913fdf2 AppKit`-[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 128 frame #10: 0x00000001005f0d2b libgstosxvideosink.so`-[GstOSXVideoSinkObject nsAppThread] + 288 frame #11: 0x00007fff8d9eb562 Foundation`__NSThread__main__ + 1345 frame #12: 0x00007fff8d4ed7a2 libsystem_c.dylib`_pthread_start + 327 frame #13: 0x00007fff8d4da1e1 libsystem_c.dylib`thread_start + 13
It looks like Cocoa's helper thread for the run loop is started more than once. I will try to fix it along the week.
Created attachment 248583 [details] [review] osxvideosink: only create the NS app thread once Only create the helper NS thread for Cocoa once and shared it across all instances.
Created attachment 248584 [details] Test app for reuse This can be tested with: gst-launch-1.0 videotestsrc ! osxvideosink videotestsrc ! osxvideosink And re-use can be tested with the sample app running twice: gst-launch-1.0 videotestsrc num-buffers=100 ! osxvideosink
When is the thread stopped? Never? Maybe implement some kind of refcounting for the thread, that makes sure it is shut down if all osxvideosink instances are gone.
I implemented something similar with an atomic to keep count of the sinks running, but I don't know if we should really do something here. When we need this helper thread we also need to initialize the application with: [NSApplication sharedApplication]; [NSApp finishLaunching]; So I'd say that in case we need a custom NS run loop running it should be initialized and started only once and kept it running until the applications ends. This thread is blocking and not polling, so it's not consuming resources.
Comment on attachment 248583 [details] [review] osxvideosink: only create the NS app thread once Makes sense then
commit 213fa3af0d5cea0faf358586c6fd5e8cb7d8314f Author: Andoni Morales Alastruey <ylatuya@gmail.com> Date: Sun Jul 7 21:14:22 2013 +0200 osxvideosink: only create the NS app thread for Cocoa once The helper thread for Cocoa, in case no NS run loop is running, should be started only once and shared across all the instances running