From 1a1871498a94b448c94561160e66de582d84cf67 Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Thu, 28 Jul 2016 18:51:24 +0200 Subject: gstv4l2bufferpool: lock flush_stop against regular qbuf These can be called from different threads and both manipulate the pool->buffers array. Lock them properly and let flush_stop move the array contents into a temporary array on the stack to avoid having to call release_buffer under the object lock. https://bugzilla.gnome.org/show_bug.cgi?id=775015 --- sys/v4l2/gstv4l2bufferpool.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/sys/v4l2/gstv4l2bufferpool.c b/sys/v4l2/gstv4l2bufferpool.c index 50630316a..3c127f8c3 100644 --- a/sys/v4l2/gstv4l2bufferpool.c +++ b/sys/v4l2/gstv4l2bufferpool.c @@ -940,6 +940,7 @@ gst_v4l2_buffer_pool_flush_stop (GstBufferPool * bpool) { GstV4l2BufferPool *pool = GST_V4L2_BUFFER_POOL (bpool); GstV4l2Object *obj = pool->obj; + GstBuffer *buffers[VIDEO_MAX_FRAME]; gint i; GST_DEBUG_OBJECT (pool, "stop flushing"); @@ -951,7 +952,12 @@ gst_v4l2_buffer_pool_flush_stop (GstBufferPool * bpool) if (pool->other_pool) gst_buffer_pool_set_flushing (pool->other_pool, FALSE); + GST_OBJECT_LOCK (pool); gst_v4l2_buffer_pool_streamoff (pool); + /* Remember buffers to re-enqueue */ + memcpy(buffers, pool->buffers, sizeof(buffers)); + memset(pool->buffers, 0, sizeof(pool->buffers)); + GST_OBJECT_UNLOCK (pool); /* Reset our state */ switch (obj->mode) { @@ -964,11 +970,9 @@ gst_v4l2_buffer_pool_flush_stop (GstBufferPool * bpool) { for (i = 0; i < VIDEO_MAX_FRAME; i++) { /* Re-enqueue buffers */ - if (pool->buffers[i]) { + if (buffers[i]) { GstBufferPool *bpool = (GstBufferPool *) pool; - GstBuffer *buffer = pool->buffers[i]; - - pool->buffers[i] = NULL; + GstBuffer *buffer = buffers[i]; /* Remove qdata, this will unmap any map data in * userptr/dmabuf-import */ @@ -1077,9 +1081,6 @@ gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool * pool, GstBuffer * buf) GST_LOG_OBJECT (pool, "queuing buffer %i", index); - g_atomic_int_inc (&pool->num_queued); - pool->buffers[index] = buf; - if (V4L2_TYPE_IS_OUTPUT (obj->type)) { enum v4l2_field field; @@ -1107,10 +1108,13 @@ gst_v4l2_buffer_pool_qbuf (GstV4l2BufferPool * pool, GstBuffer * buf) GST_TIME_TO_TIMEVAL (timestamp, group->buffer.timestamp); } + GST_OBJECT_LOCK (pool); + g_atomic_int_inc (&pool->num_queued); + pool->buffers[index] = buf; + if (!gst_v4l2_allocator_qbuf (pool->vallocator, group)) goto queue_failed; - GST_OBJECT_LOCK (pool); pool->empty = FALSE; g_cond_signal (&pool->empty_cond); GST_OBJECT_UNLOCK (pool); @@ -1129,6 +1133,7 @@ queue_failed: GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_TAG_MEMORY); g_atomic_int_add (&pool->num_queued, -1); pool->buffers[index] = NULL; + GST_OBJECT_UNLOCK (pool); return GST_FLOW_ERROR; } } -- cgit v1.2.1