From 1ca5513396b4fa52f7305e19b7db0ae525dbd730 Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Thu, 26 Aug 2021 09:23:44 -0400 Subject: gstreamer: Fix deadlock when last allocator ref is held by buffer 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 Reviewed-by: Laurent Pinchart Tested-by: Kieran Bingham Signed-off-by: Laurent Pinchart --- src/gstreamer/gstlibcameraallocator.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'src/gstreamer') 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(gst_mini_object_get_qdata(mini_object, FrameWrap::getQuark())); - gst_memory_ref(mem); + { + GLibLocker lock(GST_OBJECT(self)); + auto *frame = reinterpret_cast(gst_mini_object_get_qdata(mini_object, FrameWrap::getQuark())); + + gst_memory_ref(mem); - if (frame->releasePlane()) { - auto *pool = reinterpret_cast(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(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. */ -- cgit v1.2.1