From 7f763f27100cb677c0f0f14b649f16a34cb56548 Mon Sep 17 00:00:00 2001 From: Jean-Christophe Trotin Date: Tue, 17 Jan 2017 16:41:58 +0100 Subject: [PATCH] v4l2allocator: reference memory before the buffer is queued In gst_v4l2_allocator_qbuf(), the memory is referenced after the buffer is queued. Once queued (VIDIOC_QBUF), the buffer might be handled by the V4L2 driver (e.g. decoded) and dequeued (gst_v4l2_allocator_dqbuf), through a different thread, before the memory is referenced (gst_memory_ref). In this case, in gst_v4l2_allocator_dqbuf(), the memory is unreferenced (gst_memory_unref) before having been referenced: the memory refcount reaches 0, and the memory is freed. So, to avoid this crossing case, in gst_v4l2_allocator_qbuf(), the memory shall be referenced before the buffer is queued. https://bugzilla.gnome.org/show_bug.cgi?id=777399 --- sys/v4l2/gstv4l2allocator.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/sys/v4l2/gstv4l2allocator.c b/sys/v4l2/gstv4l2allocator.c index 7d9b1ec241..20473830ae 100644 --- a/sys/v4l2/gstv4l2allocator.c +++ b/sys/v4l2/gstv4l2allocator.c @@ -1240,9 +1240,18 @@ gst_v4l2_allocator_qbuf (GstV4l2Allocator * allocator, group->buffer.bytesused = gst_memory_get_sizes (group->mem[0], NULL, NULL); } + /* Ensure the memory will stay around and is RO */ + for (i = 0; i < group->n_mem; i++) + gst_memory_ref (group->mem[i]); + if (v4l2_ioctl (allocator->video_fd, VIDIOC_QBUF, &group->buffer) < 0) { GST_ERROR_OBJECT (allocator, "failed queueing buffer %i: %s", group->buffer.index, g_strerror (errno)); + + /* Release the memory, possibly making it RW again */ + for (i = 0; i < group->n_mem; i++) + gst_memory_unref (group->mem[i]); + ret = FALSE; if (IS_QUEUED (group->buffer)) { GST_DEBUG_OBJECT (allocator, @@ -1261,10 +1270,6 @@ gst_v4l2_allocator_qbuf (GstV4l2Allocator * allocator, SET_QUEUED (group->buffer); } - /* Ensure the memory will stay around and is RO */ - for (i = 0; i < group->n_mem; i++) - gst_memory_ref (group->mem[i]); - done: return ret; }