summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Christophe Trotin <jean-christophe.trotin@st.com>2017-01-17 16:41:58 +0100
committerNicolas Dufresne <nicolas.dufresne@collabora.com>2017-02-21 16:48:23 -0500
commit3c911b5a6ba8d3e69240ec72a892afc36f40e923 (patch)
tree4d65fb26b4b879e594ebb56e103f62058d2c2b7b
parent4a57ff75449e1ba525df28c8b99ff9fd566430a3 (diff)
downloadgstreamer-plugins-good-3c911b5a6ba8d3e69240ec72a892afc36f40e923.tar.gz
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
-rw-r--r--sys/v4l2/gstv4l2allocator.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/sys/v4l2/gstv4l2allocator.c b/sys/v4l2/gstv4l2allocator.c
index 7d9b1ec24..20473830a 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;
}