From 2062558ad9f5265fcc2f7f8c2365f39a4e44a3f1 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Mon, 11 Aug 2025 08:33:21 -0400 Subject: [PATCH] MT#55283 clean up RTCP send locking Fixes regression from Ib4285e7aae RTCP multiplexing requires the RTCP sender to maybe lock the same output stream, maybe lock some other one. Allow for both. Change-Id: I6fcef32e656f8f0de46ad777f11a19c259ce35c7 (cherry picked from commit cec0afa25e1c0b29be8d93433dec3a52ddc67514) (cherry picked from commit d1d4110f0ffd7fa63ba38c180b579848f3d2b08e) (cherry picked from commit ea26245c4ddd9808f97465da0b65dffbcd6abdeb) (cherry picked from commit 9f5bc1be2e7ec88e82dcb2be7f6f51cfe475c11c) --- daemon/codec.c | 2 +- daemon/media_player.c | 7 +++++-- daemon/rtcp.c | 22 ++++++++++++++-------- include/rtcp.h | 3 ++- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/daemon/codec.c b/daemon/codec.c index d8e8097b8..b1bf80d7c 100644 --- a/daemon/codec.c +++ b/daemon/codec.c @@ -968,7 +968,7 @@ static void __rtcp_timer_run(struct codec_timer *ct) { if (!ssrc_out[u]) // end of list break; // coverity[use : FALSE] - rtcp_send_report(media, ssrc_out[u]); + rtcp_send_report(media, ssrc_out[u], NULL); } rwlock_unlock_r(&rt->call->master_lock); diff --git a/daemon/media_player.c b/daemon/media_player.c index 4b2ffff5d..fdaaa9615 100644 --- a/daemon/media_player.c +++ b/daemon/media_player.c @@ -215,12 +215,13 @@ struct send_timer *send_timer_new(struct packet_stream *ps) { // call is locked in R // ssrc_out is locked +// st->sink is locked static void send_timer_rtcp(struct send_timer *st, struct ssrc_ctx *ssrc_out) { struct call_media *media = st->sink ? st->sink->media : NULL; if (!media) return; - rtcp_send_report(media, ssrc_out); + rtcp_send_report(media, ssrc_out, st->sink); ssrc_out->next_rtcp = rtpe_now; timeval_add_usec(&ssrc_out->next_rtcp, 5000000 + (ssl_random() % 2000000)); @@ -295,6 +296,7 @@ out: codec_packet_free(cp); } +// sink->lock is held static void __send_timer_rtcp(struct send_timer *st, struct ssrc_ctx *ssrc_out) { // do we send RTCP? if (!ssrc_out) @@ -323,9 +325,10 @@ static void send_timer_send_lock(struct send_timer *st, struct codec_packet *cp) __send_timer_send_common(st, cp); + __send_timer_rtcp(st, ssrc_out); + mutex_unlock(&st->sink->lock); - __send_timer_rtcp(st, ssrc_out); ssrc_ctx_put(&ssrc_out); rwlock_unlock_r(&call->master_lock); diff --git a/daemon/rtcp.c b/daemon/rtcp.c index 5c2e8ab5b..a7a4b4cba 100644 --- a/daemon/rtcp.c +++ b/daemon/rtcp.c @@ -1557,8 +1557,10 @@ void rtcp_receiver_reports(GQueue *out, struct ssrc_hash *hash, struct call_mono // call must be locked in R -// no in_lock or out_lock must be held -void rtcp_send_report(struct call_media *media, struct ssrc_ctx *ssrc_out) { +// if a `ps` is locked, it must be passed as argument +void rtcp_send_report(struct call_media *media, struct ssrc_ctx *ssrc_out, + const struct packet_stream *locked) +{ // figure out where to send it struct packet_stream *ps = media->streams.head->data; // crypto context is held separately @@ -1569,18 +1571,17 @@ void rtcp_send_report(struct call_media *media, struct ssrc_ctx *ssrc_out) { else { if (PS_ISSET(rtcp_ps, RTCP)) ps = rtcp_ps; - else - rtcp_ps = ps; } media_update_stats(media); - LOCK(&ps->lock); + if (ps != locked) + mutex_lock(&ps->lock); - if (!ps->selected_sfd || !rtcp_ps->selected_sfd) - return; + if (!ps->selected_sfd) + goto out; if (ps->selected_sfd->socket.fd == -1 || ps->endpoint.address.family == NULL) - return; + goto out; log_info_stream_fd(ps->selected_sfd); @@ -1634,6 +1635,11 @@ void rtcp_send_report(struct call_media *media, struct ssrc_ctx *ssrc_out) { struct ssrc_receiver_report *srr = g_queue_pop_head(&srrs); g_slice_free1(sizeof(*srr), srr); } + +out: + if (ps != locked) + mutex_unlock(&ps->lock); + } diff --git a/include/rtcp.h b/include/rtcp.h index ef4622621..99235732e 100644 --- a/include/rtcp.h +++ b/include/rtcp.h @@ -39,6 +39,7 @@ void rtcp_init(void); void rtcp_receiver_reports(GQueue *out, struct ssrc_hash *hash, struct call_monologue *ml); -void rtcp_send_report(struct call_media *media, struct ssrc_ctx *ssrc_out); +void rtcp_send_report(struct call_media *media, struct ssrc_ctx *ssrc_out, + const struct packet_stream *locked); #endif