From efa62628147c2607033e77f8854fd47bd51d3928 Mon Sep 17 00:00:00 2001 From: Richard Mudgett Date: Wed, 16 Aug 2017 15:22:04 -0500 Subject: bridge: Fix softmix bridge deadlock. * Fix deadlock in bridge_softmix.c:softmix_bridge_stream_topology_changed() between bridge_channel and channel locks. * The new bridge technology topology change callbacks must be called with the bridge locked. The callback references the bridge channel list, the bridge technology could change, and the bridge stream mapping is updated. ASTERISK-27212 Change-Id: Ide4360ab853607e738ad471721af3f561ddd83be --- main/bridge_channel.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'main/bridge_channel.c') diff --git a/main/bridge_channel.c b/main/bridge_channel.c index 1427fd014..c465ec16e 100644 --- a/main/bridge_channel.c +++ b/main/bridge_channel.c @@ -2434,6 +2434,7 @@ static const char *controls[] = { static void bridge_handle_trip(struct ast_bridge_channel *bridge_channel) { struct ast_frame *frame; + int blocked; if (!ast_strlen_zero(ast_channel_call_forward(bridge_channel->chan))) { /* TODO If early bridging is ever used by anything other than ARI, @@ -2485,10 +2486,16 @@ static void bridge_handle_trip(struct ast_bridge_channel *bridge_channel) ast_channel_publish_dial(NULL, bridge_channel->chan, NULL, controls[frame->subclass.integer]); break; case AST_CONTROL_STREAM_TOPOLOGY_REQUEST_CHANGE: - if (bridge_channel->bridge->technology->stream_topology_request_change && - bridge_channel->bridge->technology->stream_topology_request_change( - bridge_channel->bridge, bridge_channel)) { - /* Topology change was denied so drop frame */ + ast_bridge_channel_lock_bridge(bridge_channel); + blocked = bridge_channel->bridge->technology->stream_topology_request_change + && bridge_channel->bridge->technology->stream_topology_request_change( + bridge_channel->bridge, bridge_channel); + ast_bridge_unlock(bridge_channel->bridge); + if (blocked) { + /* + * Topology change was intercepted by the bridge technology + * so drop frame. + */ bridge_frame_free(frame); return; } @@ -2498,12 +2505,14 @@ static void bridge_handle_trip(struct ast_bridge_channel *bridge_channel) * If a stream topology has changed then the bridge_channel's * media mapping needs to be updated. */ + ast_bridge_channel_lock_bridge(bridge_channel); if (bridge_channel->bridge->technology->stream_topology_changed) { bridge_channel->bridge->technology->stream_topology_changed( bridge_channel->bridge, bridge_channel); } else { ast_bridge_channel_stream_map(bridge_channel); } + ast_bridge_unlock(bridge_channel->bridge); break; default: break; @@ -2990,9 +2999,11 @@ struct ast_bridge_channel *bridge_channel_internal_alloc(struct ast_bridge *brid void ast_bridge_channel_stream_map(struct ast_bridge_channel *bridge_channel) { + ast_bridge_channel_lock(bridge_channel); ast_channel_lock(bridge_channel->chan); ast_stream_topology_map(ast_channel_get_stream_topology(bridge_channel->chan), &bridge_channel->bridge->media_types, &bridge_channel->stream_map.to_bridge, &bridge_channel->stream_map.to_channel); ast_channel_unlock(bridge_channel->chan); + ast_bridge_channel_unlock(bridge_channel); } -- cgit v1.2.3