Race condition in ipcpipelinesrc during flush
Submitted by Mike Dyer
Created attachment 373802
[PATCH] Fix race condition during flush
A race condition exists when handling flush-start and flush-stop events in intersrc.
When receiving a flush-start event, the event handler calls gst_inter_src_stop_loop() which sets the flag src->flushing. In the case of pausing the task, it does not wait for gst_inter_src_loop() to pause itself.
gst_inter_src_loop() reads the value of src->flushing while holding src->comm.mutex and stores it in a local variable. After releasing the mutex, gst_inter_src_loop() then proceeds to clear the queue and then set itself to paused, based on the value of the local variable.
During the queue clearing, it is possible that a flush-stop event could arrive. This will clear src->flushing and call gst_pad_start_task() to schedule gst_inter_src_loop(). However, the task hasn't paused yet, so this call does nothing. gst_inter_src_loop() finishes clearing the queue and sets itself to paused. Because this occurs after receipt of the flush-stop, the loop remains paused and is not restarted.
To prevent this, we can pause the task from gst_inter_src_stop_loop(). This will then wait for the gst_inter_src_loop() to complete. We can also clear the queue after it completes, removing the vulnerable period (gst_inter_src_cancel_queued() cannot be called from inside gst_inter_src_loop() with the mutex held, as it locks this mutex itself).
We must also propagate the flush-start event before attempting to pause gst_inter_src_loop() as it may be blocked pushing to downstream elements.
Patch 373802, "[PATCH] Fix race condition during flush":