mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-12 15:45:18 +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:
@@ -509,6 +509,8 @@ enum ast_bridge_impart_flags {
|
||||
* \param features Bridge features structure.
|
||||
* \param flags defined by enum ast_bridge_impart_flags.
|
||||
*
|
||||
* \note The given bridge must be unlocked when calling this function.
|
||||
*
|
||||
* \note The features parameter must be NULL or obtained by
|
||||
* ast_bridge_features_new(). You must not dereference features
|
||||
* after calling even if the call fails.
|
||||
|
@@ -129,11 +129,48 @@ int bridge_channel_internal_push(struct ast_bridge_channel *bridge_channel);
|
||||
*/
|
||||
void bridge_channel_internal_pull(struct ast_bridge_channel *bridge_channel);
|
||||
|
||||
/*!
|
||||
* \brief Internal bridge channel wait condition and associated result.
|
||||
*/
|
||||
struct bridge_channel_internal_cond {
|
||||
/*! Lock for the data structure */
|
||||
ast_mutex_t lock;
|
||||
/*! Wait condition */
|
||||
ast_cond_t cond;
|
||||
/*! Wait until done */
|
||||
int done;
|
||||
/*! The bridge channel */
|
||||
struct ast_bridge_channel *bridge_channel;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Wait for the expected signal.
|
||||
* \since 13.5.0
|
||||
*
|
||||
* \param cond the wait object
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
void bridge_channel_internal_wait(struct bridge_channel_internal_cond *cond);
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Signal the condition wait.
|
||||
* \since 13.5.0
|
||||
*
|
||||
* \param cond the wait object
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
void bridge_channel_internal_signal(struct bridge_channel_internal_cond *cond);
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Join the bridge_channel to the bridge (blocking)
|
||||
*
|
||||
* \param bridge_channel The Channel in the bridge
|
||||
* \param cond data used for signaling
|
||||
*
|
||||
* \note The bridge_channel->swap holds a channel reference for the swap
|
||||
* channel going into the bridging system. The ref ensures that the swap
|
||||
@@ -148,7 +185,8 @@ void bridge_channel_internal_pull(struct ast_bridge_channel *bridge_channel);
|
||||
* \retval 0 bridge channel successfully joined the bridge
|
||||
* \retval -1 bridge channel failed to join the bridge
|
||||
*/
|
||||
int bridge_channel_internal_join(struct ast_bridge_channel *bridge_channel);
|
||||
int bridge_channel_internal_join(struct ast_bridge_channel *bridge_channel,
|
||||
struct bridge_channel_internal_cond *cond);
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
|
Reference in New Issue
Block a user