rtpsession: fix a race condition during the EOS event in gstrtpsession.c.
rtpsession: fix a race condition during the EOS event in gstrtpsession.c.
This patch prevents a possible race condition from taking place between the EOS event handling and rtcp send function/thread.
The condition starts by getting the GST_EVENT_EOS
event on the send_rtp_sink
pad, which causes two core things to happen -- the event gets pushed down to the send_rtp_src
pad and all sessions get marked "bye" prior to completion of the event handler. In another thread the rtp_session_on_timeout
function gets called after an expiration of gst_clock_id_wait
in the rtcp_thread
function. This results in a call to ess->callbacks.send_rtcp()
, which is configured as a function pointer to gst_rtp_session_send_rtcp
via the RTPSessionCallbacks
structure passed to rtp_session_set_callbacks
in the gst_rtp_session_init
function.
In the race condition, the call to gst_rtp_session_send_rtcp
can have the all_sources_bye
boolean set to true while GST_PAD_IS_EOS(rtpsession->send_rtp_sink)
evaluates to false. This is the result of gst_rtp_session_send_rtcp
running before the send_rtp_sink
's GST_EVENT_EOS
handler completes. The exact point at which this condition occurs is if there's a context switch to the rtcp_thread
right after the call to rtp_session_mark_all_bye
in the GET_EVENT_EOS
handler, but before the handler returns.
Normally, this would not be an issue because the rtcp_thread
continues to run and indirectly call gst_rtp_session_send_rtcp
. However, the call to rtp_source_reset
sets the sent_bye
boolean to false, which ends up causing rtp_session_are_all_sources_bye
to return false. This gets passed to gst_rtp_session_send_rtcp
and the EOS event never gets sent.
The race condition results in the EOS event never getting passed to the rtcp_src
pad, which prevents the bin and pipeline from ever completing with EOS.