videotestsrc: fix race condition when clearing cached buffer
Discovered a crash due to race condition with src->cached
. It is non-null when checked on L1307, but gets cleared from a separate thread on L767 before the null pointer is then accessed on L1321.
My solution is to use a flag to invalidate the cache rather than clear it directly.
edit: after discussion w/@slomo, I added a mutex around cached
buffer.
I believe the bug first appears in gstreamer 1.22
python script to reproduce:
import sys
import traceback
import threading
import time
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject, GLib
Gst.init(sys.argv)
ll = 'videotestsrc name=tstsrc is-live=true pattern=17 ! queue ! fakesink'
def on_message(bus: Gst.Bus, message: Gst.Message, loop: GLib.MainLoop):
mtype = message.type
if mtype == Gst.MessageType.EOS:
print("End of stream")
loop.quit()
elif mtype == Gst.MessageType.ERROR:
err, debug = message.parse_error()
print(err, debug)
loop.quit()
elif mtype == Gst.MessageType.WARNING:
err, debug = message.parse_warning()
print(err, debug)
return True
pipeline = Gst.parse_launch(ll)
bus = pipeline.get_bus()
bus.add_signal_watch()
pipeline.set_state(Gst.State.PLAYING)
print('started pipeline')
loop = GLib.MainLoop()
bus.connect("message", on_message, loop)
def hammer():
global pipeline
while True:
ele = pipeline.get_by_name('tstsrc')
time.sleep(.0001)
ele.set_property('foreground-color', int(0x1234567))
time.sleep(5)
t = threading.Thread(target=hammer)
t.start()
try:
loop.run()
except Exception:
traceback.print_exc()
loop.quit()
pipeline.set_state(Gst.State.NULL)
Edited by Joshua Breeden