Deadlock when setting pipeline to NULL while appsrc is pushing a segment
I hit a fun deadlock in my app. This is with 1.22.5
.
There are two objects involved:
-
appsrc
:0x55f3fbbf36e0
- its
pipeline
:0x7fbc64008a40
On one thread we have appsrc
trying to push a segment:
-
appsrc
is holding its object lock (gst_base_src_push_segment
) -
appsrc
is holdingappsrc->mutex
(not relevant here) -
pipeline
is waiting on its object lock
Thread 143 (Thread 0x7fbb457fa640 (LWP 122693)):
#0 syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38
#1 0x00007fbd6b13911c in () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#2 0x00007fbd6b271f0d in gst_object_get_parent (object=0x7fbc64008a40) at ../subprojects/gstreamer/gst/gstobject.c:759
#3 0x00007fbd6b27208d in gst_object_dispatch_properties_changed (object=0x7fb730ad5850, n_pspecs=1, pspecs=0x7fbb457f8e80) at ../subprojects/gstreamer/gst/gstobject.c:480
#4 0x00007fbd6b1f405a in g_object_notify_by_pspec () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0
#5 0x00007fbd6b2bc2cd in store_sticky_event (pad=pad@entry=0x7fb730ad5850, event=event@entry=0x7fbbec003270) at ../subprojects/gstreamer/gst/gstpad.c:5394
#6 0x00007fbd6b2c718c in gst_pad_push_event (pad=pad@entry=0x7fb730ad5850, event=0x7fbbec003270) at ../subprojects/gstreamer/gst/gstpad.c:5691
#7 0x00007fbd6b3d6c48 in gst_pad_set_caps (caps=0x7fb93407db20, pad=0x7fb730ad5850) at ../subprojects/gstreamer/gst/gstcompat.h:59
#8 gst_base_transform_setcaps (trans=trans@entry=0x55f3fbbea8d0, pad=<optimized out>, incaps=0x7fb93407db20) at ../subprojects/gstreamer/libs/gst/base/gstbasetransform.c:1346
#9 0x00007fbd6b3d823a in gst_base_transform_sink_eventfunc (trans=0x55f3fbbea8d0, event=0x7fbbec003200) at ../subprojects/gstreamer/libs/gst/base/gstbasetransform.c:1951
#10 0x00007fbcc6b66c23 in gst_video_rate_sink_event (trans=0x55f3fbbea8d0, event=0x7fbbec003200) at ../subprojects/gst-plugins-base/gst/videorate/gstvideorate.c:1119
#11 0x00007fbd6b2bd854 in gst_pad_send_event_unchecked (pad=pad@entry=0x7fb730ad5cf0, event=event@entry=0x7fbbec003200, type=<optimized out>) at ../subprojects/gstreamer/gst/gstpad.c:5939
#12 0x00007fbd6b2c7591 in gst_pad_send_event (pad=0x7fb730ad5cf0, event=0x7fbbec003200) at ../subprojects/gstreamer/gst/gstpad.c:6109
#13 0x00007fbcc6b6703a in gst_video_rate_sink_event (trans=0x55f3fbbea8d0, event=0x7fbaec0a22d0) at ../subprojects/gst-plugins-base/gst/videorate/gstvideorate.c:991
#14 0x00007fbd6b2bd854 in gst_pad_send_event_unchecked (pad=pad@entry=0x7fb730ad5cf0, event=event@entry=0x7fbaec0a22d0, type=<optimized out>, type@entry=GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM) at ../subprojects/gstreamer/gst/gstpad.c:5939
#15 0x00007fbd6b2bdf04 in gst_pad_push_event_unchecked (pad=pad@entry=0x55f3fbf99da0, event=0x7fbaec0a22d0, type=<optimized out>, type@entry=GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM) at ../subprojects/gstreamer/gst/gstpad.c:5572
#16 0x00007fbd6b2be418 in push_sticky (pad=pad@entry=0x55f3fbf99da0, ev=ev@entry=0x7fbb457f94f0, user_data=user_data@entry=0x7fbb457f9560) at ../subprojects/gstreamer/gst/gstevent.h:430
#17 0x00007fbd6b2baff7 in events_foreach (pad=pad@entry=0x55f3fbf99da0, func=func@entry=0x7fbd6b2be330 <push_sticky>, user_data=user_data@entry=0x7fbb457f9560) at ../subprojects/gstreamer/gst/gstpad.c:613
#18 0x00007fbd6b2c73a3 in check_sticky (event=0x7fbaec0a22d0, pad=0x55f3fbf99da0) at ../subprojects/gstreamer/gst/gstpad.c:4116
#19 gst_pad_push_event (pad=0x55f3fbf99da0, event=event@entry=0x7fbaec0a22d0) at ../subprojects/gstreamer/gst/gstpad.c:5705
#20 0x00007fbd6b3d25d4 in gst_base_src_push_segment (src=src@entry=0x55f3fbbf36e0, segment=0x7fb6c4001e30) at ../subprojects/gstreamer/libs/gst/base/gstbasesrc.c:4198
#21 0x00007fbd6ade6fb8 in gst_app_src_create (bsrc=0x55f3fbbf36e0, offset=<optimized out>, size=4096, buf=0x7fbb457f96e8) at ../subprojects/gst-plugins-base/gst-libs/gst/app/gstappsrc.c:1790
#22 0x00007fbd6b3cb1ed in gst_base_src_get_range (src=src@entry=0x55f3fbbf36e0, offset=offset@entry=18446744073709551615, length=<optimized out>, length@entry=4096, buf=buf@entry=0x7fbb457f97c0) at ../subprojects/gstreamer/libs/gst/base/gstbasesrc.c:2592
#23 0x00007fbd6b3ce2ac in gst_base_src_loop (pad=0x55f3fbf99da0) at ../subprojects/gstreamer/libs/gst/base/gstbasesrc.c:2916
#24 0x00007fbd6b2f6107 in gst_task_func (task=0x7fb79443a4d0) at ../subprojects/gstreamer/gst/gsttask.c:384
#25 0x00007fbd6b11c6a4 in () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#26 0x00007fbd6b119a41 in () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#27 0x00007fbd6a7dfb43 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#28 0x00007fbd6a871a00 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
On the other thread the application is trying to set pipeline
to NULL
:
-
pipeline
is holding its state lock (not relevant here) -
pipeline
is holding its object lock (gst_bin_iterate_sorted
) -
appsrc
is waiting on its object lock
Thread 155 (Thread 0x7fbca1ffb640 (LWP 124686)):
#0 syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38
#1 0x00007fbd6b13911c in () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#2 0x00007fbd6b278a50 in reset_degree (element=0x55f3fbbf36e0, bit=0x7fbafeea4cb0) at ../subprojects/gstreamer/gst/gstbin.c:2191
#3 0x00007fbd6b0e4f60 in g_list_foreach () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#4 0x00007fbd6b275f7b in gst_bin_sort_iterator_resync (bit=bit@entry=0x7fbafeea4cb0) at ../subprojects/gstreamer/gst/gstbin.c:2370
#5 0x00007fbd6b27603b in gst_bin_sort_iterator_new (bin=bin@entry=0x7fbc64008a40) at ../subprojects/gstreamer/gst/gstbin.c:2412
#6 0x00007fbd6b27c437 in gst_bin_iterate_sorted (bin=0x7fbc64008a40) at ../subprojects/gstreamer/gst/gstbin.c:2438
#7 0x00007fbd6b27c67f in gst_bin_change_state_func (element=0x7fbc64008a40, transition=GST_STATE_CHANGE_PLAYING_TO_PAUSED) at ../subprojects/gstreamer/gst/gstbin.c:2906
#8 0x00007fbd6b2cb606 in gst_pipeline_change_state (element=0x7fbc64008a40, transition=GST_STATE_CHANGE_PLAYING_TO_PAUSED) at ../subprojects/gstreamer/gst/gstpipeline.c:529
#9 0x00007fbd6b2a0062 in gst_element_change_state (element=element@entry=0x7fbc64008a40, transition=transition@entry=GST_STATE_CHANGE_PLAYING_TO_PAUSED) at ../subprojects/gstreamer/gst/gstelement.c:3093
#10 0x00007fbd6b2a07a9 in gst_element_set_state_func (element=0x7fbc64008a40, state=GST_STATE_NULL) at ../subprojects/gstreamer/gst/gstelement.c:3047
#11 0x00007fbd6b29b3b2 in gst_element_call_async_func (data=0x55f3fbeeb510, user_data=<optimized out>) at ../subprojects/gstreamer/gst/gstelement.c:3832
#12 0x00007fbd6b11c6a4 in () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#13 0x00007fbd6b119a41 in () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#14 0x00007fbd6a7dfb43 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
#15 0x00007fbd6a871a00 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
As a result we have a deadlock between appsrc
and pipeline
object locks.
I suppose basesrc
should release the object lock before pushing the segment?