From ba2834314e4149e6e7c1eecc8d5ce69d73601494 Mon Sep 17 00:00:00 2001 From: Donat Zenichev Date: Tue, 21 Jul 2026 16:19:54 +0200 Subject: [PATCH] MT#55283 media_socket: lock sink earlier when kernelizing To not come across the sink's mutation (e.g. `endpoint.address.family`) just lock way earlier, before to start processing and translating endpoint to the kernel related structs. Otherwise the other signaling path may mutate something which will make the sink unactual and provide to the `__re_address_translate_ep()` NULLed or garbage structs. Change-Id: I88d87ae88abe4e37aaa5d3cdda76ed0ca82e4842 (cherry picked from commit e16a2309e0c72809930d848f2f2d265beb4dde60) --- daemon/media_socket.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/daemon/media_socket.c b/daemon/media_socket.c index ee0dbbb03..d3c0519e7 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -1784,8 +1784,17 @@ static const char *kernelize_one(kernelize_state *s, if (MEDIA_ISSET(sink_media, BLOCK_EGRESS)) return NULL; - if (!sink->endpoint.address.family) + /* XXX nested lock, avoid possible deadlock. should be reworked not to + * require a nested lock */ + if (sink != stream && mutex_trylock(&sink->lock)) { + return ""; // indicate deadlock + } + + if (!sink->endpoint.address.family) { + if (sink != stream) + mutex_unlock(&sink->lock); return NULL; + } if (sink->selected_sfd) ilog(LOG_INFO, "Kernelizing media stream: %s%s%s -> %s | %s -> %s%s%s", @@ -1800,16 +1809,25 @@ static const char *kernelize_one(kernelize_state *s, const struct streamhandler *handler = determine_sink_handler(stream, sink_handler); - if (!handler->out->kernel) + if (!handler->out->kernel) { + if (sink != stream) + mutex_unlock(&sink->lock); return "protocol not supported by kernel module"; + } __auto_type reti = &s->reti.target; // any output at all? - if (s->non_forwarding || !sink->selected_sfd || !sink->selected_sfd->socket.family) + if (s->non_forwarding || !sink->selected_sfd || !sink->selected_sfd->socket.family) { + if (sink != stream) + mutex_unlock(&sink->lock); return NULL; // no output - if (!PS_ISSET(sink, FILLED)) + } + if (!PS_ISSET(sink, FILLED)) { + if (sink != stream) + mutex_unlock(&sink->lock); return NULL; + } // fill output struct __auto_type credi = g_new0(struct rtpengine_command_destination, 1); @@ -1850,13 +1868,6 @@ static const char *kernelize_one(kernelize_state *s, if (MEDIA_ISSET(media, ECHO) || sink_handler->attrs.transcoding) redi->output.ssrc_subst = 1; - // XXX nested lock, avoid possible deadlock. should be reworked not to - // require a nested lock - if (sink != stream && mutex_trylock(&sink->lock)) { - g_free(credi); - return ""; // indicate deadlock - } - __re_address_translate_ep(&redi->output.dst_addr, &sink->endpoint); __re_address_translate_ep(&redi->output.src_addr, &sink->selected_sfd->socket.local); redi->output.iface_stats = sink->selected_sfd->local_intf->stats;