v4l2: SIGSEGV when doing 'change state' during 'format change'
Observed Behavior
When playing a HLS video that has a 'resolution change' and changing state (stopping playback) during the resolution change I'm getting a SIGSEGV.
Setup
- Operating System: Raspberry Pi OS 11 (bullseye)
- Device: Raspberry Pi 400
- GStreamer Version: 1.21.0 (GIT), commit: b09ae1d6
-
Build command line:
meson builddir -Dgst-plugins-base:gl=disabled
-
Command line:
gst-launch-1.0 --no-fault souphttpsrc location="$HLS1" ! hlsdemux ! parsebin ! v4l2h264dec ! autovideosink
Steps to reproduce the bug
see: https://github.com/stawel/gstreamer-tests/tree/main/format-change
- checkout above repo
- in terminal 1:
cd format-change
python -m http.server
- in terminal 2:
cd format-change
./readme.txt
after a while you should get:
...
################################### Tue 28 Jun 2022 05:26:47 PM CEST #### test 20, sleep time 5.282498487952571
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
Got context from element 'souphttpsrc0': gst.soup.session=context, session=(GstSoupSession)NULL;
Got context from element 'souphttpsrc1': gst.soup.session=context, session=(GstSoupSession)NULL;
Redistribute latency...
Redistribute latency...
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
Redistribute latency...
New clock: GstSystemClock
Got context from element 'souphttpsrc1': gst.soup.session=context, session=(GstSoupSession)NULL;
0:00:03.3 / 0:00:12.0 (28.2 %)
** (gst-launch-1.0:14838): WARNING **: 17:26:51.762: v4l2h264dec0: Too old frames, bug in decoder -- please file a bug
** (gst-launch-1.0:14838): WARNING **: 17:26:51.768: v4l2h264dec0: Too old frames, bug in decoder -- please file a bug
** (gst-launch-1.0:14838): WARNING **: 17:26:51.769: v4l2h264dec0: Too old frames, bug in decoder -- please file a bug
handling interrupt..0 (40.8 %)
Interrupt: Stopping pipeline ...
Execution ended after 0:00:04.951858206
Setting pipeline to NULL ...
./readme.txt: line 30: 14838 Segmentation fault (core dumped) gst-launch-1.0 --no-fault souphttpsrc location="$HLS1" ! hlsdemux ! parsebin ! v4l2h264dec ! autovideosink
pi@raspberrypi:~/format-change $
How reproducible is the bug?
with the script above it take about 5 minutes to reproduce
gdb core callstack
Core was generated by `gst-launch-1.0 --no-fault souphttpsrc location=http://localhost:8000/resolution'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 malloc_consolidate (av=av@entry=0x7f50000020) at malloc.c:4475
4475 malloc.c: No such file or directory.
[Current thread is 1 (Thread 0x7f57fff180 (LWP 4369))]
(gdb) bt
#0 malloc_consolidate (av=av@entry=0x7f50000020) at malloc.c:4475
#1 0x0000007f80e5b210 in _int_malloc (av=av@entry=0x7f50000020, bytes=bytes@entry=127297) at malloc.c:3699
#2 0x0000007f80e5cc38 in __GI___libc_malloc (bytes=127297) at malloc.c:3066
#3 0x0000007f8104db40 in g_malloc () at /lib/aarch64-linux-gnu/libglib-2.0.so.0
#4 0x0000007f7dc49a30 in gst_adapter_get_internal (adapter=adapter@entry=0x7f4800bea0, nbytes=nbytes@entry=127297) at ../subprojects/gstreamer/libs/gst/base/gstadapter.c:736
#5 0x0000007f7dc4b048 in gst_adapter_get_buffer (adapter=adapter@entry=0x7f4800bea0, nbytes=nbytes@entry=127297) at ../subprojects/gstreamer/libs/gst/base/gstadapter.c:1012
#6 0x0000007f7dc4b158 in gst_adapter_take_buffer (adapter=0x7f4800bea0, nbytes=127297) at ../subprojects/gstreamer/libs/gst/base/gstadapter.c:1076
#7 0x0000007f7c2f40d0 in gst_h264_parse_parse_frame (parse=<optimized out>, frame=0x7f50122630) at ../subprojects/gst-plugins-bad/gst/videoparsers/gsth264parse.c:2720
#8 0x0000007f7c2f5820 in gst_h264_parse_handle_frame (parse=<optimized out>, frame=0x7f50122630, skipsize=0x7f57ffd8a4) at ../subprojects/gst-plugins-bad/gst/videoparsers/gsth264parse.c:1579
#9 0x0000007f7dc5f1e4 in gst_base_parse_handle_buffer (parse=parse@entry=0x7f500cbaa0, buffer=<optimized out>, skip=skip@entry=0x7f57ffd8a4, flushed=flushed@entry=0x7f57ffd8a8)
at ../subprojects/gstreamer/libs/gst/base/gstbaseparse.c:2253
#10 0x0000007f7dc64614 in gst_base_parse_chain (pad=<optimized out>, parent=<optimized out>, buffer=<optimized out>) at ../subprojects/gstreamer/libs/gst/base/gstbaseparse.c:3302
#11 0x0000007f811d7570 in gst_pad_chain_data_unchecked (pad=pad@entry=0x7f5c00af60, type=type@entry=4112, data=<optimized out>, data@entry=0x7f501487e0) at ../subprojects/gstreamer/gst/gstpad.c:4444
#12 0x0000007f811d9370 in gst_pad_push_data (pad=pad@entry=0x7f5c00aac0, type=type@entry=4112, data=data@entry=0x7f501487e0) at ../subprojects/gstreamer/gst/gstpad.c:4708
#13 0x0000007f811e0c88 in gst_pad_push (pad=0x7f5c00aac0, buffer=buffer@entry=0x7f501487e0) at ../subprojects/gstreamer/gst/gstpad.c:4827
#14 0x0000007f7c420f40 in gst_ts_demux_push_pending_data (demux=demux@entry=0x7f5c008ce0, stream=stream@entry=0x7f500c56b0, target_program=target_program@entry=0x0)
at ../subprojects/gst-plugins-bad/gst/mpegtsdemux/tsdemux.c:3544
#15 0x0000007f7c422790 in gst_ts_demux_handle_packet (section=<optimized out>, packet=<optimized out>, stream=0x7f500c56b0, demux=0x7f5c008ce0)
at ../subprojects/gst-plugins-bad/gst/mpegtsdemux/tsdemux.c:3632
#16 gst_ts_demux_push (base=0x7f5c008ce0, packet=<optimized out>, section=<optimized out>) at ../subprojects/gst-plugins-bad/gst/mpegtsdemux/tsdemux.c:3700
...
valgrind logs
==13800== Invalid write of size 4
==13800== at 0x4B98CE8: pthread_mutex_lock (pthread_mutex_lock.c:118)
==13800== by 0x48B66EF: gst_buffer_pool_is_active (gstbufferpool.c:598)
==13800== by 0xA9F1C0B: gst_v4l2_object_unlock (gstv4l2object.c:4563)
==13800== by 0xAA04AF3: gst_v4l2_video_dec_change_state (gstv4l2videodec.c:1059)
==13800== by 0x48D48EB: gst_element_change_state (gstelement.c:3093)
==13800== by 0x48D5093: gst_element_set_state_func (gstelement.c:3047)
==13800== by 0x48AE863: gst_bin_element_set_state (gstbin.c:2581)
==13800== by 0x48AE863: gst_bin_change_state_func (gstbin.c:2923)
==13800== by 0x4900E5B: gst_pipeline_change_state (gstpipeline.c:529)
==13800== by 0x48D48EB: gst_element_change_state (gstelement.c:3093)
==13800== by 0x48D492B: gst_element_change_state (gstelement.c:3132)
==13800== by 0x48D5093: gst_element_set_state_func (gstelement.c:3047)
==13800== by 0x10BD0F: main (gst-launch.c:1339)
==13800== Address 0x8b191e4 is 4 bytes inside a block of size 48 free'd
==13800== at 0x484AFE0: free (vg_replace_malloc.c:538)
==13800== by 0x48B6037: gst_buffer_pool_finalize (gstbufferpool.c:213)
==13800== by 0x4B3B95F: g_object_unref (in /usr/lib/aarch64-linux-gnu/libgobject-2.0.so.0.6600.8)
==13800== by 0xA9F84D7: gst_v4l2_buffer_pool_orphan (gstv4l2bufferpool.c:1049)
==13800== by 0xA9F1D63: gst_v4l2_object_stop (gstv4l2object.c:4593)
==13800== by 0xAA06CDB: gst_v4l2_video_dec_set_format (gstv4l2videodec.c:274)
==13800== by 0x9EC235F: gst_video_decoder_setcaps (gstvideodecoder.c:897)
==13800== by 0x9EC235F: gst_video_decoder_sink_event_default (gstvideodecoder.c:1379)
==13800== by 0x48F30F3: gst_pad_send_event_unchecked (gstpad.c:5897)
==13800== by 0x48F352F: gst_pad_push_event_unchecked (gstpad.c:5541)
==13800== by 0x48F3B0B: push_sticky (gstpad.c:4044)
==13800== by 0x48F16DF: events_foreach (gstpad.c:605)
==13800== by 0x48FCC87: check_sticky (gstpad.c:4103)
==13800== by 0x48FCC87: gst_pad_push_event (gstpad.c:5672)
==13800== Block was alloc'd at
==13800== at 0x4849E4C: malloc (vg_replace_malloc.c:307)
==13800== by 0x4A84167: ??? (in /usr/lib/aarch64-linux-gnu/libglib-2.0.so.0.6600.8)
==13800== by 0x4A841F3: g_rec_mutex_init (in /usr/lib/aarch64-linux-gnu/libglib-2.0.so.0.6600.8)
==13800== by 0x48B6E07: gst_buffer_pool_init (gstbufferpool.c:160)
==13800== by 0x4B56787: g_type_create_instance (in /usr/lib/aarch64-linux-gnu/libgobject-2.0.so.0.6600.8)
==13800== by 0x4B3BE87: ??? (in /usr/lib/aarch64-linux-gnu/libgobject-2.0.so.0.6600.8)
==13800== by 0x4B3DCF3: g_object_new_valist (in /usr/lib/aarch64-linux-gnu/libgobject-2.0.so.0.6600.8)
==13800== by 0x4B3DF6F: g_object_new (in /usr/lib/aarch64-linux-gnu/libgobject-2.0.so.0.6600.8)
==13800== by 0xA9F8593: gst_v4l2_buffer_pool_new (gstv4l2bufferpool.c:1819)
==13800== by 0xA9E93B3: gst_v4l2_object_setup_pool (gstv4l2object.c:3161)
==13800== by 0xA9EC97B: gst_v4l2_object_set_format_full (gstv4l2object.c:4045)
==13800== by 0xAA06D17: gst_v4l2_video_dec_set_format (gstv4l2videodec.c:304)
Additional Information
It looks like the heap is corrupted.
Reason (from valgrind logs):
gst_v4l2_video_dec_change_state(...)
is touching something what was released in a different thread by gst_v4l2_video_dec_set_format(...)