mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-03 11:25:35 +00:00
bridge.c: Fixed race condition during attended transfer
During an attended transfer a thread is started that handles imparting the bridge channel. From the start of the thread to when the bridge channel is ready exists a gap that can potentially cause problems (for instance, the channel being swapped is hung up before the replacement channel enters the bridge thus stopping the transfer). This patch adds a condition that waits for the impart thread to get to a point of acceptable readiness before allowing the initiating thread to continue. ASTERISK-24782 Reported by: John Bigelow Change-Id: I08fe33a2560da924e676df55b181e46fca604577
This commit is contained in:
@@ -2560,7 +2560,27 @@ static void bridge_channel_event_join_leave(struct ast_bridge_channel *bridge_ch
|
||||
ao2_iterator_destroy(&iter);
|
||||
}
|
||||
|
||||
int bridge_channel_internal_join(struct ast_bridge_channel *bridge_channel)
|
||||
void bridge_channel_internal_wait(struct bridge_channel_internal_cond *cond)
|
||||
{
|
||||
ast_mutex_lock(&cond->lock);
|
||||
while (!cond->done) {
|
||||
ast_cond_wait(&cond->cond, &cond->lock);
|
||||
}
|
||||
ast_mutex_unlock(&cond->lock);
|
||||
}
|
||||
|
||||
void bridge_channel_internal_signal(struct bridge_channel_internal_cond *cond)
|
||||
{
|
||||
if (cond) {
|
||||
ast_mutex_lock(&cond->lock);
|
||||
cond->done = 1;
|
||||
ast_cond_signal(&cond->cond);
|
||||
ast_mutex_unlock(&cond->lock);
|
||||
}
|
||||
}
|
||||
|
||||
int bridge_channel_internal_join(struct ast_bridge_channel *bridge_channel,
|
||||
struct bridge_channel_internal_cond *cond)
|
||||
{
|
||||
int res = 0;
|
||||
struct ast_bridge_features *channel_features;
|
||||
@@ -2590,6 +2610,7 @@ int bridge_channel_internal_join(struct ast_bridge_channel *bridge_channel)
|
||||
bridge_channel->bridge->uniqueid,
|
||||
bridge_channel,
|
||||
ast_channel_name(bridge_channel->chan));
|
||||
bridge_channel_internal_signal(cond);
|
||||
return -1;
|
||||
}
|
||||
ast_channel_internal_bridge_set(bridge_channel->chan, bridge_channel->bridge);
|
||||
@@ -2624,6 +2645,8 @@ int bridge_channel_internal_join(struct ast_bridge_channel *bridge_channel)
|
||||
}
|
||||
bridge_reconfigured(bridge_channel->bridge, !bridge_channel->inhibit_colp);
|
||||
|
||||
bridge_channel_internal_signal(cond);
|
||||
|
||||
if (bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT) {
|
||||
/*
|
||||
* Indicate a source change since this channel is entering the
|
||||
|
Reference in New Issue
Block a user