From: Pirmin Walthert Date: Wed, 30 May 2018 06:12:30 +0000 (+0200) Subject: bridge_channel.c: Fix Deadlock when using Local channels and fax gateway X-Git-Tag: 15.5.0-rc1~48^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1958c9e1585d4f3ec80396a4762b76e2422d05f5;p=thirdparty%2Fasterisk.git bridge_channel.c: Fix Deadlock when using Local channels and fax gateway ast_indicate is invoked with the bridge locked. As ast_indicate locks the other end of the bridge as well this can lead to a deadlock in some situations. (Especially when a different thread does the same in the reverse order). This patch calls ast_indicate after unlocking the bridge which fixes the deadlock. Calling ast_indicate with these parameters without locking the bridge should be safe as this is done at different places without a bridge lock. ASTERISK-27094 #close Reported-by: David Brillert Change-Id: I5f86c1e2ce75b9929a36ab589b18c450e62ea35f --- diff --git a/main/bridge_channel.c b/main/bridge_channel.c index eb4b9ad0e8..7d7d26a6b8 100644 --- a/main/bridge_channel.c +++ b/main/bridge_channel.c @@ -2820,6 +2820,7 @@ static void bridge_channel_event_join_leave(struct ast_bridge_channel *bridge_ch int bridge_channel_internal_join(struct ast_bridge_channel *bridge_channel) { int res = 0; + uint8_t indicate_src_change = 0; struct ast_bridge_features *channel_features; struct ast_channel *swap; @@ -2889,7 +2890,7 @@ int bridge_channel_internal_join(struct ast_bridge_channel *bridge_channel) */ if (!(bridge_channel->bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX)) { - ast_indicate(bridge_channel->chan, AST_CONTROL_SRCCHANGE); + indicate_src_change = 1; } bridge_channel_impart_signal(bridge_channel->chan); @@ -2899,6 +2900,10 @@ int bridge_channel_internal_join(struct ast_bridge_channel *bridge_channel) ao2_t_cleanup(swap, "Bridge push with swap successful"); swap = NULL; + if (indicate_src_change) { + ast_indicate(bridge_channel->chan, AST_CONTROL_SRCCHANGE); + } + bridge_channel_event_join_leave(bridge_channel, AST_BRIDGE_HOOK_TYPE_JOIN); while (bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT) {