Repository navigation
staging: vc04_services: bcm2835-codec: Signal every buffer returned during a flush - #7713
rahmounirabii wants to merge 1 commit into
Conversation
|
Independent confirmation from a different board, and evidence that the lost/early completion is more than a 2 s stall: on a decoder it leads to a use-after-free and a hung kernel. Setup: Pi Zero W (armv6), What happens. GStreamer's stateful decoder stops only the CAPTURE queue while OUTPUT keeps streaming on start-up renegotiation, on a resolution change and on an EOS drain (
Kernel log (netconsole), in order: On other runs the first fault was Our fix (minimal), which stopped it completely: signal only when the last buffer is back, at the three existing sites: - if (!port->enabled && atomic_read(&port->buffers_with_vpu))
+ if (!port->enabled && !atomic_read(&port->buffers_with_vpu))
complete(&ctx->frame_cmplt);(likewise the This PR reaches the same end differently — completing for every returned buffer (including the EOS/error early returns, which our patch does not cover) and looping in 🤖 Generated with Claude Code |
…uring a flush buffers_with_vpu is decremented in buffer_work_cb() before the buffer callback runs. With the port disabled, ip_buffer_cb() and op_buffer_cb() only signalled frame_cmplt if the counter was still non-zero, so the callback of the last returned buffer never signalled. When bcm2835_codec_flush_buffers() saw one buffer still with the VPU, it then slept the whole COMPLETE_TIMEOUT (2 s) under dev_mutex and logged "Timeout waiting for buffers to be returned - 0 outstanding", stalling QBUF/DQBUF of every other decoder instance meanwhile (a video playing in another instance freezes for ~2 s). With several buffers outstanding, the same condition made the single wait in bcm2835_codec_flush_buffers() return on the first returned buffer rather than the last. For a decoder, stopping the CAPTURE queue while the input port is still enabled then re-enables the output port, and op_buffer_cb() resubmits the empty buffers the VPU returns after that with vchiq_mmal_submit_buffer() instead of handing them back to videobuf2. Eliran Sapir reported this on a Pi Zero W running two concurrent H.264 decodes: videobuf2 warns that stop_streaming leaves buffers in active state, followed by faults in buffer_work_cb and a hung board. Signal frame_cmplt for every buffer returned while the port is disabled, including the EOS and error paths that are also counted in buffers_with_vpu, and make the flush wait loop while buffers remain with the VPU, each wait still bounded by COMPLETE_TIMEOUT. The flush now returns once no buffer is left with the VPU, or after a COMPLETE_TIMEOUT expires with one still outstanding. Link: raspberrypi#7712 Link: raspberrypi#7713 (comment) Signed-off-by: Rabii Rahmouni <rahmounirabii.me@gmail.com>
3479796 to
a8f2f90
Compare
|
Thank you for the independent report and the detailed log. I checked the paths you describe against the driver source: with several buffers outstanding, the conditional To be precise about what I observed myself: on the Pi 4B I only saw the 2 s stall described in #7712; I have not reproduced the resubmission or the crash there. With this patch each wait is still bounded by If you get a chance to run this exact patch on the Zero W, the result would be very useful. |
buffers_with_vpu is decremented in buffer_work_cb() before the buffer callback runs. With the port disabled, ip_buffer_cb() and op_buffer_cb() only signalled frame_cmplt if the counter was still non-zero, so the callback of the last returned buffer never signalled. When bcm2835_codec_flush_buffers() saw one buffer still with the VPU, it then slept the whole COMPLETE_TIMEOUT (2 s) under dev_mutex and logged "Timeout waiting for buffers to be returned - 0 outstanding", stalling QBUF/DQBUF of every other decoder instance meanwhile (a video playing in another instance freezes for ~2 s).
Signal frame_cmplt for every buffer returned while the port is disabled, including the EOS and error paths that are also counted in buffers_with_vpu, and make the flush wait loop while buffers remain with the VPU, each wait still bounded by COMPLETE_TIMEOUT.
Tested on a Pi 4B (6.18.50+rpt-rpi-v8): no occurrence of the timeout since 22 Oct, over ~45 h of signage playback plus an 8 h stress run (~4,700 decoder reuse cycles while another video plays). Details and reproduction in #7712.
Fixes #7712