diff options
author | Kevin Harwell <kharwell@digium.com> | 2015-07-08 14:56:10 -0500 |
---|---|---|
committer | Kevin Harwell <kharwell@digium.com> | 2015-07-13 12:57:56 -0500 |
commit | c8555235195ed1deb37f5e27390b0ed4da329dc5 (patch) | |
tree | 45d9a85a0858cf8e0dc9daeab658dcc3f6ef3f08 /include/asterisk | |
parent | 66b57b10f65bee8600c01a0fc03fb491edb7ad76 (diff) |
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
Diffstat (limited to 'include/asterisk')
-rw-r--r-- | include/asterisk/bridge.h | 2 | ||||
-rw-r--r-- | include/asterisk/bridge_channel_internal.h | 40 |
2 files changed, 41 insertions, 1 deletions
diff --git a/include/asterisk/bridge.h b/include/asterisk/bridge.h index 8243a1ddb..8858cf02c 100644 --- a/include/asterisk/bridge.h +++ b/include/asterisk/bridge.h @@ -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. diff --git a/include/asterisk/bridge_channel_internal.h b/include/asterisk/bridge_channel_internal.h index 71892f51a..e3fb73d7e 100644 --- a/include/asterisk/bridge_channel_internal.h +++ b/include/asterisk/bridge_channel_internal.h @@ -130,10 +130,47 @@ 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 |