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: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1478>
This commit is contained in:
Nicolas Dufresne 2022-01-17 11:44:47 -05:00 committed by GStreamer Marge Bot
parent 08aa930fee
commit 01857d7941

View file

@ -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 */