summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Dufresne <nicolas.dufresne@collabora.com>2021-08-26 09:23:44 -0400
committerLaurent Pinchart <laurent.pinchart@ideasonboard.com>2021-08-26 16:42:35 +0300
commit1ca5513396b4fa52f7305e19b7db0ae525dbd730 (patch)
treeff9df1794a96e6565377cc7fb8699e7cc3101628
parentaf1f731f473fd66cb3c6a9764b5204af3ed6bc88 (diff)
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 <nicolas.dufresne@collabora.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r--src/gstreamer/gstlibcameraallocator.cpp17
1 files 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. */