[libcamera-devel] [PATCH v1 1/3] gstreamer: Fix deadlock when last allocator ref is held by buffer
Laurent Pinchart
laurent.pinchart at ideasonboard.com
Thu Aug 26 00:42:03 CEST 2021
Hi Nicolas,
Thank you for the patch.
On Wed, Aug 25, 2021 at 05:18:50PM -0400, Nicolas Dufresne wrote:
> From: Nicolas Dufresne <nicolas.dufresne at collabora.com>
>
> This deadlock occurs when a buffer is holding the last reference on
> the allocator. In gst_libcamera_allocator_release() we must drop the
> object lock before dropping the last ref of that object since the
> destructor will lock it again causing deadlock.
>
> This was notice while switching camera or resolution in Cheese software.
>
> Signed-off-by: Nicolas Dufresne <nicolas.dufresne at collabora.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> ---
> src/gstreamer/gstlibcameraallocator.cpp | 17 ++++++++++-------
> 1 file changed, 10 insertions(+), 7 deletions(-)
>
> diff --git a/src/gstreamer/gstlibcameraallocator.cpp b/src/gstreamer/gstlibcameraallocator.cpp
> index 7bd8ba2d..a8fa4f86 100644
> --- a/src/gstreamer/gstlibcameraallocator.cpp
> +++ b/src/gstreamer/gstlibcameraallocator.cpp
> @@ -108,15 +108,18 @@ gst_libcamera_allocator_release(GstMiniObject *mini_object)
> {
> GstMemory *mem = GST_MEMORY_CAST(mini_object);
> GstLibcameraAllocator *self = GST_LIBCAMERA_ALLOCATOR(mem->allocator);
> - GLibLocker lock(GST_OBJECT(self));
> - auto *frame = reinterpret_cast<FrameWrap *>(gst_mini_object_get_qdata(mini_object, FrameWrap::getQuark()));
>
> - gst_memory_ref(mem);
> + {
> + GLibLocker lock(GST_OBJECT(self));
> + auto *frame = reinterpret_cast<FrameWrap *>(gst_mini_object_get_qdata(mini_object, FrameWrap::getQuark()));
> +
> + gst_memory_ref(mem);
>
> - if (frame->releasePlane()) {
> - auto *pool = reinterpret_cast<GQueue *>(g_hash_table_lookup(self->pools, frame->stream_));
> - g_return_val_if_fail(pool, TRUE);
> - g_queue_push_tail(pool, frame);
> + if (frame->releasePlane()) {
> + auto *pool = reinterpret_cast<GQueue *>(g_hash_table_lookup(self->pools, frame->stream_));
> + g_return_val_if_fail(pool, TRUE);
> + g_queue_push_tail(pool, frame);
> + }
> }
>
> /* Keep last in case we are holding on the last allocator ref. */
--
Regards,
Laurent Pinchart
More information about the libcamera-devel
mailing list