diff --git a/daemon/media_socket.c b/daemon/media_socket.c index ddd7bfa3c..8591effef 100644 --- a/daemon/media_socket.c +++ b/daemon/media_socket.c @@ -1747,8 +1747,17 @@ static const char *kernelize_one(kernelize_state *s, return NULL; sink_handler->kernel_output_idx = -1; - 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", @@ -1763,16 +1772,25 @@ static const char *kernelize_one(kernelize_state *s, const struct streamhandler *handler = __determine_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; // 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 redi = g_new0(struct rtpengine_destination_info, 1); @@ -1810,13 +1828,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(redi); - 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;