Skip to content

audiobase: Protect ringbuffer access in the clock

While looking into a crash, I found the root cause was an element calling gst_clock_get_time() on an audio source where the state had been set back to NULL, freeing the ringbuffer.

I came to the conclusion that the clock implementations of GstAudioBaseSrc and GstAudioBaseSink are inherently unsafe the way they are, and only avoid crashes because static pipelines don't access the clock. When dynamically modifying a pipeline and removing the element that's providing the clock though, it's really easy.

The core problem is that the gst_audio_base_src_get_time and gst_audio_base_sink_get_time implementations access the ringbuffer without taking any locks, and the ringbuffer is destroyed in the element state change method. The only way I can see to make things safe is adding some locking, despite the potential overhead. I opted for a GRWLock, so multiple calls into gst_clock_get_time() don't block each other.

When calculating the current clock position, use a lock that
protects the ringbuffer from disappearing and causing segfaults
if someone holds onto the GstAudioClock and calls get_time()
while the audio sink or source are changing state.

Merge request reports