From 01857d794165e976e1766e0dd6fa24af1561f47c Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Mon, 17 Jan 2022 11:44:47 -0500 Subject: [PATCH] v4l2videdec: Fix race condition between drain and state changes This is due to an unsafe usage of the pad task. We didn't ensure proper ownership of the task. That race involved the task being released too early, and was detected, luckily, by the glib mutex implementationt that reported the mutex being disposed while being locked. Part-of: --- .../sys/v4l2/gstv4l2videodec.c | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/subprojects/gst-plugins-good/sys/v4l2/gstv4l2videodec.c b/subprojects/gst-plugins-good/sys/v4l2/gstv4l2videodec.c index 097f3cae6b..abd01333cb 100644 --- a/subprojects/gst-plugins-good/sys/v4l2/gstv4l2videodec.c +++ b/subprojects/gst-plugins-good/sys/v4l2/gstv4l2videodec.c @@ -421,16 +421,26 @@ gst_v4l2_video_dec_finish (GstVideoDecoder * decoder) GST_VIDEO_DECODER_STREAM_UNLOCK (decoder); if (gst_v4l2_decoder_cmd (self->v4l2output, V4L2_DEC_CMD_STOP, 0)) { - GstTask *task = decoder->srcpad->task; + GstTask *task; - /* If the decoder stop command succeeded, just wait until processing is - * finished */ - GST_DEBUG_OBJECT (self, "Waiting for decoder stop"); - GST_OBJECT_LOCK (task); - while (GST_TASK_STATE (task) == GST_TASK_STARTED) - GST_TASK_WAIT (task); - GST_OBJECT_UNLOCK (task); - ret = GST_FLOW_FLUSHING; + GST_OBJECT_LOCK (decoder->srcpad); + task = GST_PAD_TASK (decoder->srcpad); + if (task) + gst_object_ref (task); + GST_OBJECT_UNLOCK (decoder->srcpad); + + if (task) { + /* If the decoder stop command succeeded, just wait until processing is + * finished */ + GST_DEBUG_OBJECT (self, "Waiting for decoder stop"); + GST_OBJECT_LOCK (task); + while (GST_TASK_STATE (task) == GST_TASK_STARTED) + GST_TASK_WAIT (task); + GST_OBJECT_UNLOCK (task); + + ret = GST_FLOW_FLUSHING; + gst_object_unref (task); + } } else { /* otherwise keep queuing empty buffers until the processing thread has * stopped, _pool_process() will return FLUSHING when that happened */