Bridging: Use a ref to bridge_channel's channel to prevent crash.

There's a race condition with bridging where a bridge can be torn down
causing the bridge_channel's ast_channel to become NULL when it's still
needed. This particular case happened with attended transfers, but the
crash occurred when trying to publish a stasis message. Now, the
bridge_channel is locked, a ref to the ast_channel is obtained, and that
ref is passed down the chain.

Change-Id: Ic48715c0c041615d17d286790ae3e8c61bb28814
This commit is contained in:
Ben Ford
2020-08-31 11:14:20 -05:00
committed by Joshua Colp
parent f8fe20eb9f
commit 80a609fcce
3 changed files with 52 additions and 3 deletions

View File

@@ -208,6 +208,17 @@ static void bridge_sync_signal(struct bridge_sync *sync_struct)
ast_sem_post(&sync_struct->sem);
}
struct ast_channel *ast_bridge_channel_get_chan(struct ast_bridge_channel *bridge_channel)
{
struct ast_channel *chan;
ao2_lock(bridge_channel);
chan = ao2_bump(bridge_channel->chan);
ao2_unlock(bridge_channel);
return chan;
}
void ast_bridge_channel_lock_bridge(struct ast_bridge_channel *bridge_channel)
{
struct ast_bridge *bridge;
@@ -1177,7 +1188,14 @@ int ast_bridge_channel_write_hold(struct ast_bridge_channel *bridge_channel, con
int ast_bridge_channel_write_unhold(struct ast_bridge_channel *bridge_channel)
{
ast_channel_publish_cached_blob(bridge_channel->chan, ast_channel_unhold_type(), NULL);
struct ast_channel *chan = ast_bridge_channel_get_chan(bridge_channel);
if (!chan) {
return -1;
}
ast_channel_publish_cached_blob(chan, ast_channel_unhold_type(), NULL);
ao2_ref(chan, -1);
return ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_UNHOLD, NULL, 0);
}